<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/Frog_32px_1177822_easyicon.net.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/Frog_32px_1177822_easyicon.net.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/Frog_16px_1177822_easyicon.net.ico">
  <link rel="mask-icon" href="/images/Frog_32px_1177822_easyicon.net.ico" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"hxy1997.xyz","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":true,"nav":null,"activeClass":"valine"},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"输入关键字","hits_empty":"没有找到与「${query}」相关搜索","hits_stats":"${hits} 条相关记录，共耗时 ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.json"};
  </script>

  <meta name="description" content="关于Promise的面试题有很多，有些一上来就很难的，有些连着几篇题目都是一样的，还有一些比较好的文章介绍的都是一些硬知识点。 这篇文章是一篇比较纯的Promise笔试文章，删改自【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理) ，原作者自己在做题的时候，根据题目想要的考点来反敲知识点，然后再由这个知识点编写从浅到深的的题目。 题目中有一些基础题，然后再从基础题慢慢的变">
<meta property="og:type" content="article">
<meta property="og:title" content="49道Promise面试题">
<meta property="og:url" content="https://hxy1997.xyz/2021/04/16/49%E9%81%93Promise%E9%9D%A2%E8%AF%95%E9%A2%98/index.html">
<meta property="og:site_name" content="hxy的博客">
<meta property="og:description" content="关于Promise的面试题有很多，有些一上来就很难的，有些连着几篇题目都是一样的，还有一些比较好的文章介绍的都是一些硬知识点。 这篇文章是一篇比较纯的Promise笔试文章，删改自【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理) ，原作者自己在做题的时候，根据题目想要的考点来反敲知识点，然后再由这个知识点编写从浅到深的的题目。 题目中有一些基础题，然后再从基础题慢慢的变">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/huxingyi1997/my_img/img/20210416201000.webp">
<meta property="article:published_time" content="2021-04-16T09:30:00.000Z">
<meta property="article:modified_time" content="2021-04-18T07:35:53.870Z">
<meta property="article:author" content="hxy">
<meta property="article:tag" content="JavaScript">
<meta property="article:tag" content="面试">
<meta property="article:tag" content="Promise">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://cdn.jsdelivr.net/gh/huxingyi1997/my_img/img/20210416201000.webp">

<link rel="canonical" href="https://hxy1997.xyz/2021/04/16/49%E9%81%93Promise%E9%9D%A2%E8%AF%95%E9%A2%98/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>49道Promise面试题 | hxy的博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="hxy的博客" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">hxy的博客</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">Mia san Mia!</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

  <a href="https://github.com/huxingyi1997" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://hxy1997.xyz/2021/04/16/49%E9%81%93Promise%E9%9D%A2%E8%AF%95%E9%A2%98/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/Robben.gif">
      <meta itemprop="name" content="hxy">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="hxy的博客">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          49道Promise面试题
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-04-16 17:30:00" itemprop="dateCreated datePublished" datetime="2021-04-16T17:30:00+08:00">2021-04-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-18 15:35:53" itemprop="dateModified" datetime="2021-04-18T15:35:53+08:00">2021-04-18</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/web%E5%89%8D%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">web前端</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="热度" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">热度：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/2021/04/16/49%E9%81%93Promise%E9%9D%A2%E8%AF%95%E9%A2%98/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/2021/04/16/49%E9%81%93Promise%E9%9D%A2%E8%AF%95%E9%A2%98/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>关于<code>Promise</code>的面试题有很多，有些一上来就很难的，有些连着几篇题目都是一样的，还有一些比较好的文章介绍的都是一些硬知识点。</p>
<p>这篇文章是一篇比较纯的<code>Promise</code>笔试文章，删改自<a target="_blank" rel="noopener" href="https://juejin.cn/post/6844904077537574919">【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理)</a> ，原作者自己在做题的时候，根据题目想要的考点来反敲知识点，然后再由这个知识点编写从浅到深的的题目。</p>
<p>题目中有一些基础题，然后再从基础题慢慢的变难，循序渐进嘛…</p>
<p>题目没有到特别深入，不过应该覆盖了大部分的考点，另外为了不把大家绕混，答案也没有考虑在<code>Node</code>的执行结果，执行结果全为浏览器环境下，当然最新的Node环境应该和浏览器环境相同了。另外promise的resolved状态打印出来的结果现在显示的fulfilled</p>
<p>OK👌， 来看看通过阅读本篇文章你可以学到：</p>
<ul>
<li>Promise的几道基础题</li>
<li>Promise结合setTimeout</li>
<li>Promise中的then、catch、finally</li>
<li>Promise中的all和race</li>
<li>async/await的几道题</li>
<li>async处理错误</li>
<li>综合题</li>
<li>自测面试题</li>
</ul>
<span id="more"></span>

<h3 id="0-前期准备"><a href="#0-前期准备" class="headerlink" title="0.前期准备"></a>0.前期准备</h3><ul>
<li><p>在做的题目之前，需要清楚事件循环的基本知识点。</p>
<p><strong><code>event loop</code>它的执行顺序：</strong></p>
<ul>
<li>一开始整个脚本作为一个宏任务执行</li>
<li>执行过程中同步代码直接执行，宏任务进入宏任务队列，微任务进入微任务队列</li>
<li>当前宏任务执行完出队，检查微任务列表，有则依次执行，直到全部执行完</li>
<li>执行浏览器UI线程的渲染工作</li>
<li>检查是否有<code>Web Worker</code>任务，有则执行</li>
<li>执行完本轮的宏任务，回到2，依此循环，直到宏任务和微任务队列都为空</li>
</ul>
<p><strong>微任务包括：</strong><code>MutationObserver</code>、<code>Promise.then()或catch()</code>、<code>Promise为基础开发的其它技术，比如fetch API</code>、<code>V8</code>的垃圾回收过程、<code>Node独有的process.nextTick</code>。</p>
<p><strong>宏任务包括</strong>：<code>script</code> 、<code>setTimeout</code>、<code>setInterval</code> 、<code>setImmediate</code> 、<code>I/O</code> 、<code>UI rendering</code>。</p>
<p><strong>注意</strong>⚠️：在所有任务开始的时候，由于宏任务中包括了<code>script</code>，所以浏览器会先执行一个宏任务，在这个过程中你看到的延迟任务(例如<code>setTimeout</code>)将被放到下一轮宏任务中来执行。</p>
</li>
</ul>
<h3 id="1-Promise的几道基础题"><a href="#1-Promise的几道基础题" class="headerlink" title="1. Promise的几道基础题"></a>1. Promise的几道基础题</h3><h4 id="1-1-题目一"><a href="#1-1-题目一" class="headerlink" title="1.1 题目一"></a>1.1 题目一</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">const promise1 &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;promise1&#39;);</span><br><span class="line">&#125;)</span><br><span class="line">console.log(&#39;1&#39;, promise1); </span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; 1 Promise&#123;&lt;pending&gt;&#125;</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<ul>
<li>从上至下，先遇到<code>new Promise</code>，执行该构造函数中的代码<code>promise1</code></li>
<li>然后执行同步代码<code>1</code>，此时<code>promise1</code>没有被<code>resolve</code>或者<code>reject</code>，因此状态还是<code>pending</code></li>
</ul>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;1&#39; Promise&#123;&lt;pending&gt;&#125;</span><br></pre></td></tr></table></figure>

<h4 id="1-2-题目二"><a href="#1-2-题目二" class="headerlink" title="1.2 题目二"></a>1.2 题目二</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">const promise &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    console.log(1);</span><br><span class="line">    resolve(&#39;success&#39;)</span><br><span class="line">    console.log(2);</span><br><span class="line">&#125;);</span><br><span class="line">promise.then(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(3);</span><br><span class="line">&#125;);</span><br><span class="line">console.log(4);</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; 4</span><br><span class="line">&#x2F;&#x2F; 3</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<ul>
<li>从上至下，先遇到<code>new Promise</code>，执行其中的同步代码<code>1</code></li>
<li>再遇到<code>resolve(&#39;success&#39;)</code>， 将<code>promise</code>的状态改为了<code>resolved</code>并且将值保存下来</li>
<li>继续执行同步代码<code>2</code></li>
<li>跳出<code>promise</code>，往下执行，碰到<code>promise.then</code>这个微任务，将其加入微任务队列</li>
<li>执行同步代码<code>4</code></li>
<li>本轮宏任务全部执行完毕，检查微任务队列，发现<code>promise.then</code>这个微任务且状态为<code>resolved</code>，执行它。</li>
</ul>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1 2 4 3</span><br></pre></td></tr></table></figure>

<h4 id="1-3-题目三"><a href="#1-3-题目三" class="headerlink" title="1.3 题目三"></a>1.3 题目三</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">const promise &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    console.log(1);</span><br><span class="line">    console.log(2);</span><br><span class="line">&#125;);</span><br><span class="line">promise.then(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(3);</span><br><span class="line">&#125;);</span><br><span class="line">console.log(4); </span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; 4</span><br></pre></td></tr></table></figure>

<p>过程分析</p>
<ul>
<li>和题目二相似，只不过在<code>promise</code>中并没有<code>resolve</code>或者<code>reject</code></li>
<li>因此<code>promise.then</code>并不会执行，它只有在被改变了状态之后才会执行。</li>
</ul>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1 2 4</span><br></pre></td></tr></table></figure>

<h4 id="1-4-题目四"><a href="#1-4-题目四" class="headerlink" title="1.4 题目四"></a>1.4 题目四</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">const promise1 &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;promise1&#39;);</span><br><span class="line">    resolve(&#39;resolve1&#39;);</span><br><span class="line">&#125;)</span><br><span class="line">const promise2 &#x3D; promise1.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;)</span><br><span class="line">console.log(&#39;1&#39;, promise1);</span><br><span class="line">console.log(&#39;2&#39;, promise2);</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; 1 Promise&#123;&lt;fulfilled&gt;: &#39;resolve1&#39;&#125;</span><br><span class="line">&#x2F;&#x2F; 2 Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#x2F;&#x2F; resolve1</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<ul>
<li>从上至下，先遇到<code>new Promise</code>，执行该构造函数中的代码<code>promise1</code></li>
<li>碰到<code>resolve</code>函数, 将<code>promise1</code>的状态改变为<code>resolved</code>, 并将结果保存下来</li>
<li>碰到<code>promise1.then</code>这个微任务，将它放入微任务队列</li>
<li><code>promise2</code>是一个新的状态为<code>pending</code>的<code>Promise</code></li>
<li>执行同步代码<code>1</code>， 同时打印出<code>promise1</code>的状态是<code>resolved</code></li>
<li>执行同步代码<code>2</code>，同时打印出<code>promise2</code>的状态是<code>pending</code></li>
<li>宏任务执行完毕，查找微任务队列，发现<code>promise1.then</code>这个微任务且状态为<code>resolved</code>，执行它。</li>
</ul>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;1&#39; Promise&#123;&lt;fulfilled&gt;: &#39;resolve1&#39;&#125;</span><br><span class="line">&#39;2&#39; Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#39;resolve1&#39;</span><br></pre></td></tr></table></figure>

<h4 id="1-5-题目五"><a href="#1-5-题目五" class="headerlink" title="1.5 题目五"></a>1.5 题目五</h4><p>接下来看看这道题：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">const fn &#x3D; () &#x3D;&gt; (new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    console.log(1);</span><br><span class="line">    resolve(&#39;success&#39;);</span><br><span class="line">&#125;))</span><br><span class="line">fn().then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;)</span><br><span class="line">console.log(&#39;start&#39;);</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; success</span><br></pre></td></tr></table></figure>

<p>这道题里最先执行的是<code>&#39;start&#39;</code>吗  ？</p>
<p>请仔细看看哦，<code>fn</code>函数它是直接返回了一个<code>new Promise</code>的，而且<code>fn</code>函数的调用是在<code>start</code>之前，所以它里面的内容应该会先执行。</p>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">&#39;start&#39;</span><br><span class="line">&#39;success&#39;</span><br></pre></td></tr></table></figure>

<h4 id="1-6-题目六"><a href="#1-6-题目六" class="headerlink" title="1.6 题目六"></a>1.6 题目六</h4><p>如果把<code>fn</code>的调用放到<code>start</code>之后呢？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">const fn &#x3D; () &#x3D;&gt;</span><br><span class="line">    new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">        console.log(1);</span><br><span class="line">        resolve(&quot;success&quot;);</span><br><span class="line">    &#125;);</span><br><span class="line">console.log(&quot;start&quot;);</span><br><span class="line">fn().then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; success</span><br></pre></td></tr></table></figure>

<p>是的，现在<code>start</code>就在<code>1</code>之前打印出来了，因为<code>fn</code>函数是之后执行的。</p>
<p><strong>注意⚠️</strong>：之前我们很容易就以为看到new Promise()就执行它的第一个参数函数了，其实这是不对的，就像这两道题中，我们得注意它是不是被包裹在函数当中，如果是的话，只有在函数调用的时候才会执行。</p>
<p>答案：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&quot;start&quot;</span><br><span class="line">1</span><br><span class="line">&quot;success&quot;</span><br></pre></td></tr></table></figure>

<h3 id="2-Promise结合setTimeout"><a href="#2-Promise结合setTimeout" class="headerlink" title="2. Promise结合setTimeout"></a>2. Promise结合setTimeout</h3><h4 id="2-1-题目一"><a href="#2-1-题目一" class="headerlink" title="2.1 题目一"></a>2.1 题目一</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">console.log(&#39;start&#39;);</span><br><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;time&#39;);</span><br><span class="line">&#125;)</span><br><span class="line">Promise.resolve().then(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;resolve&#39;);</span><br><span class="line">&#125;)</span><br><span class="line">console.log(&#39;end&#39;);</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; end</span><br><span class="line">&#x2F;&#x2F; resolve</span><br><span class="line">&#x2F;&#x2F; time</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<ul>
<li>刚开始整个脚本作为一个宏任务来执行，对于同步代码直接压入执行栈进行执行，因此先打印出<code>start</code>和<code>end</code>。</li>
<li><code>setTimout</code>作为一个宏任务被放入宏任务队列(下一个)</li>
<li><code>Promise.then</code>作为一个微任务被放入微任务队列</li>
<li>本次宏任务执行完，检查微任务，发现<code>Promise.then</code>，执行它</li>
<li>接下来进入下一个宏任务，发现<code>setTimeout</code>，执行。</li>
</ul>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;start&#39;</span><br><span class="line">&#39;end&#39;</span><br><span class="line">&#39;resolve&#39;</span><br><span class="line">&#39;time&#39;</span><br></pre></td></tr></table></figure>

<h4 id="2-2-题目二"><a href="#2-2-题目二" class="headerlink" title="2.2 题目二"></a>2.2 题目二</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">const promise &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    console.log(1);</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&quot;timerStart&quot;);</span><br><span class="line">        resolve(&quot;success&quot;);</span><br><span class="line">        console.log(&quot;timerEnd&quot;);</span><br><span class="line">    &#125;, 0);</span><br><span class="line">    console.log(2);</span><br><span class="line">&#125;);</span><br><span class="line">promise.then((res) &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;);</span><br><span class="line">console.log(4);</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; 4</span><br><span class="line">&#x2F;&#x2F; timerStart</span><br><span class="line">&#x2F;&#x2F; timerEnd</span><br><span class="line">&#x2F;&#x2F; success</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<p>和题目<code>1.2</code>很像，不过在<code>resolve</code>的外层加了一层<code>setTimeout</code>定时器。</p>
<ul>
<li>从上至下，先遇到<code>new Promise</code>，执行该构造函数中的代码<code>1</code></li>
<li>然后碰到了定时器，将这个定时器中的函数放到下一个宏任务的延迟队列中等待执行</li>
<li>执行同步代码<code>2</code></li>
<li>跳出<code>promise</code>函数，遇到<code>promise.then</code>，但其状态还是为<code>pending</code>，这里理解为先不执行</li>
<li>执行同步代码<code>4</code></li>
<li>一轮循环过后，进入第二次宏任务，发现延迟队列中有<code>setTimeout</code>定时器，执行它</li>
<li>首先执行<code>timerStart</code>，然后遇到了<code>resolve</code>，将<code>promise</code>的状态改为<code>resolved</code>且保存结果并将之前的<code>promise.then</code>推入微任务队列</li>
<li>继续执行同步代码<code>timerEnd</code></li>
<li>宏任务全部执行完毕，查找微任务队列，发现<code>promise.then</code>这个微任务，执行它。</li>
</ul>
<p>因此执行结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">4</span><br><span class="line">&quot;timerStart&quot;</span><br><span class="line">&quot;timerEnd&quot;</span><br><span class="line">&quot;success&quot;</span><br></pre></td></tr></table></figure>

<h4 id="2-3-题目三"><a href="#2-3-题目三" class="headerlink" title="2.3 题目三"></a>2.3 题目三</h4><p>题目三分了两个题目，因为看着都差不多，不过执行的结果却不一样，大家不妨先猜猜下面两个题目分别执行什么：</p>
<p><strong>(1)</strong>:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;timer1&#39;);</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;timer3&#39;)</span><br><span class="line">    &#125;, 0);</span><br><span class="line">&#125;, 0);</span><br><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;timer2&#39;);</span><br><span class="line">&#125;, 0);</span><br><span class="line">console.log(&#39;start&#39;);</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; timer1</span><br><span class="line">&#x2F;&#x2F; timer2</span><br><span class="line">&#x2F;&#x2F; timer3</span><br></pre></td></tr></table></figure>

<p><strong>(2)</strong>:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;timer1&#39;);</span><br><span class="line">    Promise.resolve().then(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;promise&#39;);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;, 0);</span><br><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;timer2&#39;);</span><br><span class="line">&#125;, 0);</span><br><span class="line">console.log(&#39;start&#39;);</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; timer1</span><br><span class="line">&#x2F;&#x2F; promise</span><br><span class="line">&#x2F;&#x2F; timer2</span><br></pre></td></tr></table></figure>

<p><strong>执行结果分别为：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;start&#39;</span><br><span class="line">&#39;timer1&#39;</span><br><span class="line">&#39;timer2&#39;</span><br><span class="line">&#39;timer3&#39;</span><br></pre></td></tr></table></figure>

<p><strong>和</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;start&#39;</span><br><span class="line">&#39;timer1&#39;</span><br><span class="line">&#39;promise&#39;</span><br><span class="line">&#39;timer2&#39;</span><br></pre></td></tr></table></figure>

<p>这两个例子，看着好像只是把第一个定时器中的内容换了一下而已。</p>
<p>一个是为定时器<code>timer3</code>，一个是为<code>Promise.then</code></p>
<p>但是如果是定时器<code>timer3</code>的话，它会在<code>timer2</code>后执行，而<code>Promise.then</code>却是在<code>timer2</code>之前执行。</p>
<p>你可以这样理解，<code>Promise.then</code>是微任务，它会被加入到本轮中的微任务列表，而定时器<code>timer3</code>是宏任务，它会被加入到下一轮的宏任务中。</p>
<p>理解完这两个案例，可以来看看下面一道比较难的题目了。</p>
<h4 id="2-3-题目三-1"><a href="#2-3-题目三-1" class="headerlink" title="2.3 题目三"></a>2.3 题目三</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve().then(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;promise1&#39;);</span><br><span class="line">    const timer2 &#x3D; setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;timer2&#39;);</span><br><span class="line">    &#125;, 0);</span><br><span class="line">&#125;);</span><br><span class="line">const timer1 &#x3D; setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;timer1&#39;);</span><br><span class="line">    Promise.resolve().then(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;promise2&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;, 0)</span><br><span class="line">console.log(&#39;start&#39;);</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; timer1</span><br><span class="line">&#x2F;&#x2F; promise2</span><br><span class="line">&#x2F;&#x2F; timer2</span><br></pre></td></tr></table></figure>

<p>这道题稍微的难一些，在<code>promise</code>中执行定时器，又在定时器中执行<code>promise</code>；</p>
<p>并且要注意的是，这里的<code>Promise</code>是直接<code>resolve</code>的，而之前的<code>new Promise</code>不一样。</p>
<p>(偷偷告诉你，这道题往下一点有流程图)</p>
<p>因此过程分析为：</p>
<ul>
<li>刚开始整个脚本作为第一次宏任务来执行，我们将它标记为<strong>宏1</strong>，从上至下执行</li>
<li>遇到<code>Promise.resolve().then</code>这个微任务，将<code>then</code>中的内容加入第一次的微任务队列标记为<strong>微1</strong></li>
<li>遇到定时器<code>timer1</code>，将它加入下一次宏任务的延迟列表，标记为<strong>宏2</strong>，等待执行(先不管里面是什么内容)</li>
<li>执行<strong>宏1</strong>中的同步代码<code>start</code></li>
<li>第一次宏任务(<strong>宏1</strong>)执行完毕，检查第一次的微任务队列(<strong>微1</strong>)，发现有一个<code>promise.then</code>这个微任务需要执行</li>
<li>执行打印出<strong>微1</strong>中同步代码<code>promise1</code>，然后发现定时器<code>timer2</code>，将它加入<strong>宏2</strong>的后面，标记为<strong>宏3</strong></li>
<li>第一次微任务队列(<strong>微1</strong>)执行完毕，执行第二次宏任务(<strong>宏2</strong>)，首先执行同步代码<code>timer1</code></li>
<li>然后遇到了<code>promise2</code>这个微任务，将它加入此次循环的微任务队列，标记为<strong>微2</strong></li>
<li><strong>宏2</strong>中没有同步代码可执行了，查找本次循环的微任务队列(<strong>微2</strong>)，发现了<code>promise2</code>，执行它</li>
<li>第二轮执行完毕，执行<strong>宏3</strong>，打印出<code>timer2</code></li>
</ul>
<p>所以结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#39;start&#39;</span><br><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;timer1&#39;</span><br><span class="line">&#39;promise2&#39;</span><br><span class="line">&#39;timer2&#39;</span><br></pre></td></tr></table></figure>

<p>如果感觉有点绕的话，可以看下面这张图，就一目了然了。</p>
<p><img data-src="https://cdn.jsdelivr.net/gh/huxingyi1997/my_img/img/20210416201000.webp" alt="img"></p>
<h4 id="2-4-题目四"><a href="#2-4-题目四" class="headerlink" title="2.4 题目四"></a>2.4 题目四</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">const promise1 &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	resolve(&#39;success&#39;);</span><br><span class="line">    &#125;, 1000);</span><br><span class="line">&#125;);</span><br><span class="line">const promise2 &#x3D; promise1.then(() &#x3D;&gt; &#123;</span><br><span class="line">	throw new Error(&#39;error!!!&#39;);</span><br><span class="line">&#125;)</span><br><span class="line">console.log(&#39;promise1&#39;, promise1);</span><br><span class="line">console.log(&#39;promise2&#39;, promise2);</span><br><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;promise1&#39;, promise1);</span><br><span class="line">    console.log(&#39;promise2&#39;, promise2);</span><br><span class="line">&#125;, 2000);</span><br><span class="line">&#x2F;&#x2F; promise1 Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#x2F;&#x2F; promise2 Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#x2F;&#x2F; Error: error!!!</span><br><span class="line">&#x2F;&#x2F; promise1 Promise&#123;&lt;fulfilled&gt;: &quot;success&quot;&#125;</span><br><span class="line">&#x2F;&#x2F; promise2 Promise&#123;&lt;rejected&gt;: Error: error!!!&#125;</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<ul>
<li>从上至下，先执行第一个<code>new Promise</code>中的函数，碰到<code>setTimeout</code>将它加入下一个宏任务列表</li>
<li>跳出<code>new Promise</code>，碰到<code>promise1.then</code>这个微任务，但其状态还是为<code>pending</code>，这里理解为先不执行</li>
<li><code>promise2</code>是一个新的状态为<code>pending</code>的<code>Promise</code></li>
<li>执行同步代码<code>console.log(&#39;promise1&#39;)</code>，且打印出的<code>promise1</code>的状态为<code>pending</code></li>
<li>执行同步代码<code>console.log(&#39;promise2&#39;)</code>，且打印出的<code>promise2</code>的状态为<code>pending</code></li>
<li>碰到第二个定时器，将其放入下一个宏任务列表</li>
<li>第一轮宏任务执行结束，并且没有微任务需要执行，因此执行第二轮宏任务</li>
<li>先执行第一个定时器里的内容，将<code>promise1</code>的状态改为<code>resolved</code>且保存结果并将之前的<code>promise1.then</code>推入微任务队列</li>
<li>该定时器中没有其它的同步代码可执行，因此执行本轮的微任务队列，也就是<code>promise1.then</code>，它抛出了一个错误，且将<code>promise2</code>的状态设置为了<code>rejected</code></li>
<li>第一个定时器执行完毕，开始执行第二个定时器中的内容</li>
<li>打印出<code>&#39;promise1&#39;</code>，且此时<code>promise1</code>的状态为<code>resolved</code></li>
<li>打印出<code>&#39;promise2&#39;</code>，且此时<code>promise2</code>的状态为<code>rejected</code></li>
</ul>
<p>完整的结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#39;promise1&#39; Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#39;promise2&#39; Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">test5.html:102 Uncaught (in promise) Error: error!!! at test.html:102</span><br><span class="line">&#39;promise1&#39; Promise&#123;&lt;fulfilled&gt;: &quot;success&quot;&#125;</span><br><span class="line">&#39;promise2&#39; Promise&#123;&lt;rejected&gt;: Error: error!!!&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-5-题目五"><a href="#2-5-题目五" class="headerlink" title="2.5 题目五"></a>2.5 题目五</h4><p>如果你上面这道题搞懂了之后，我们就可以来做做这道了，你应该能很快就给出答案：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">const promise1 &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        resolve(&quot;success&quot;);</span><br><span class="line">        console.log(&quot;timer1&quot;);</span><br><span class="line">    &#125;, 1000);</span><br><span class="line">    console.log(&quot;promise1里的内容&quot;);</span><br><span class="line">&#125;);</span><br><span class="line">const promise2 &#x3D; promise1.then(() &#x3D;&gt; &#123;</span><br><span class="line">	throw new Error(&quot;error!!!&quot;);</span><br><span class="line">&#125;);</span><br><span class="line">console.log(&quot;promise1&quot;, promise1);</span><br><span class="line">console.log(&quot;promise2&quot;, promise2);</span><br><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&quot;timer2&quot;);</span><br><span class="line">    console.log(&quot;promise1&quot;, promise1);</span><br><span class="line">    console.log(&quot;promise2&quot;, promise2);</span><br><span class="line">&#125;, 2000);</span><br><span class="line">&#x2F;&#x2F; promise1里的内容</span><br><span class="line">&#x2F;&#x2F; promise1 Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#x2F;&#x2F; promise2 Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#x2F;&#x2F; timer1</span><br><span class="line">&#x2F;&#x2F; Error: error!!!</span><br><span class="line">&#x2F;&#x2F; promise1 Promise&#123;&lt;fulfilled&gt;: &quot;success&quot;&#125;</span><br><span class="line">&#x2F;&#x2F; promise2 Promise&#123;&lt;rejected&gt;: Error: error!!!&#125;</span><br></pre></td></tr></table></figure>

<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#39;promise1里的内容&#39;</span><br><span class="line">&#39;promise1&#39; Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#39;promise2&#39; Promise&#123;&lt;pending&gt;&#125;</span><br><span class="line">&#39;timer1&#39;</span><br><span class="line">test5.html:102 Uncaught (in promise) Error: error!!! at test.html:102</span><br><span class="line">&#39;timer2&#39;</span><br><span class="line">&#39;promise1&#39; Promise&#123;&lt;fulfilled&gt;: &quot;success&quot;&#125;</span><br><span class="line">&#39;promise2&#39; Promise&#123;&lt;rejected&gt;: Error: error!!!&#125;</span><br></pre></td></tr></table></figure>

<h3 id="3-Promise中的then、catch、finally"><a href="#3-Promise中的then、catch、finally" class="headerlink" title="3. Promise中的then、catch、finally"></a>3. Promise中的then、catch、finally</h3><p>把这一章知识点都列举出来，做个总结而已。当然，你也可以先不看，先去做后面的题，然后再回过头来看这些，你就觉得这些点都好好懂啊，甚至都不需要记。</p>
<h4 id="总结："><a href="#总结：" class="headerlink" title="总结："></a><strong>总结：</strong></h4><ol>
<li><code>Promise</code>的状态一经改变就不能再改变。(见3.1)</li>
<li><code>.then</code>和<code>.catch</code>都会返回一个新的<code>Promise</code>。(上面的1.4证明了)</li>
<li><code>catch</code>不管被连接到哪里，都能捕获上层未捕捉过的错误。(见3.2)</li>
<li>在<code>Promise</code>中，返回任意一个非 <code>promise</code> 的值都会被包裹成 <code>promise</code> 对象，例如<code>return 2</code>会被包装为<code>return Promise.resolve(2)</code>。</li>
<li><code>Promise</code> 的 <code>.then</code> 或者 <code>.catch</code> 可以被调用多次, 但如果<code>Promise</code>内部的状态一经改变，并且有了一个值，那么后续每次调用<code>.then</code>或者<code>.catch</code>的时候都会直接拿到该值。(见3.5)</li>
<li><code>.then</code> 或者 <code>.catch</code> 中 <code>return</code> 一个 <code>error</code> 对象并不会抛出错误，所以不会被后续的 <code>.catch</code> 捕获。(见3.6)</li>
<li><code>.then</code> 或 <code>.catch</code> 返回的值不能是 promise 本身，否则会造成死循环。(见3.7)</li>
<li><code>.then</code> 或者 <code>.catch</code> 的参数期望是函数，传入非函数则会发生值透传。(见3.8)</li>
<li><code>.then</code>方法是能接收两个参数的，第一个是处理成功的函数，第二个是处理失败的函数，再某些时候你可以认为<code>catch</code>是<code>.then</code>第二个参数的简便写法。(见3.9)</li>
<li><code>.finally</code>方法也是返回一个<code>Promise</code>，他在<code>Promise</code>结束的时候，无论结果为<code>resolved</code>还是<code>rejected</code>，都会执行里面的回调函数。</li>
</ol>
<h4 id="3-1-题目一"><a href="#3-1-题目一" class="headerlink" title="3.1 题目一"></a>3.1 题目一</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">const promise &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    resolve(&quot;success1&quot;);</span><br><span class="line">    reject(&quot;error&quot;);</span><br><span class="line">    resolve(&quot;success2&quot;);</span><br><span class="line">&#125;);</span><br><span class="line">promise</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;then: &quot;, res);</span><br><span class="line">&#125;).catch(err &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;catch: &quot;, err);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; then: success1</span><br></pre></td></tr></table></figure>

<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&quot;then: success1&quot;</span><br></pre></td></tr></table></figure>

<p>构造函数中的 <code>resolve</code> 或 <code>reject</code> 只有第一次执行有效，多次调用没有任何作用 。验证了第一个结论，<code>Promise</code>的状态一经改变就不能再改变。</p>
<h4 id="3-2-题目二"><a href="#3-2-题目二" class="headerlink" title="3.2 题目二"></a>3.2 题目二</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">const promise &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    reject(&quot;error&quot;);</span><br><span class="line">    resolve(&quot;success2&quot;);</span><br><span class="line">&#125;);</span><br><span class="line">promise</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;then1: &quot;, res);</span><br><span class="line">&#125;).then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;then2: &quot;, res);</span><br><span class="line">&#125;).catch(err &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;catch: &quot;, err);</span><br><span class="line">&#125;).then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;then3: &quot;, res);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; catch: error</span><br><span class="line">&#x2F;&#x2F; then3: undefined</span><br></pre></td></tr></table></figure>

<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&quot;catch: &quot; &quot;error&quot;</span><br><span class="line">&quot;then3: &quot; undefined</span><br></pre></td></tr></table></figure>

<p>验证了第三个结论，<code>catch</code>不管被连接到哪里，都能捕获上层未捕捉过的错误。</p>
<p>至于<code>then3</code>也会被执行，那是因为<code>catch()</code>也会返回一个<code>Promise</code>，且由于这个<code>Promise</code>没有返回值，所以打印出来的是<code>undefined</code>。</p>
<h4 id="3-3-题目三"><a href="#3-3-题目三" class="headerlink" title="3.3 题目三"></a>3.3 题目三</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve(1)</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">    console.log(res);</span><br><span class="line">    return 2;</span><br><span class="line">&#125;)</span><br><span class="line">.catch(err &#x3D;&gt; &#123;</span><br><span class="line">	return 3;</span><br><span class="line">&#125;)</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br></pre></td></tr></table></figure>

<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td></tr></table></figure>

<p><code>Promise</code>可以链式调用，不过<code>promise</code> 每次调用 <code>.then</code> 或者 <code>.catch</code> 都会返回一个新的 <code>promise</code>，从而实现了链式调用, 它并不像一般我们任务的链式调用一样<code>return this</code>。</p>
<p>上面的输出结果之所以依次打印出<code>1</code>和<code>2</code>，那是因为<code>resolve(1)</code>之后走的是第一个<code>then</code>方法，并没有走<code>catch</code>里，所以第二个<code>then</code>中的<code>res</code>得到的实际上是第一个<code>then</code>的返回值。</p>
<p>且<code>return 2</code>会被包装成<code>resolve(2)</code></p>
<h4 id="3-4-题目四"><a href="#3-4-题目四" class="headerlink" title="3.4 题目四"></a>3.4 题目四</h4><p>如果把<code>3.3</code>中的<code>Promise.resolve(1)</code>改为<code>Promise.reject(1)</code>又会怎么样呢？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Promise.reject(1)</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">    console.log(res);</span><br><span class="line">    return 2;</span><br><span class="line">&#125;)</span><br><span class="line">.catch(err &#x3D;&gt; &#123;</span><br><span class="line">    console.log(err);</span><br><span class="line">    return 3;</span><br><span class="line">&#125;)</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">3</span><br></pre></td></tr></table></figure>

<p>结果打印的当然是 <code>1</code> 和 <code>3</code>啦，因为<code>reject(1)</code>此时走的就是<code>catch</code>，且第二个<code>then</code>中的<code>res</code>得到的就是<code>catch</code>中的返回值。</p>
<h4 id="3-5-题目五"><a href="#3-5-题目五" class="headerlink" title="3.5 题目五"></a>3.5 题目五</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">const promise &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;timer&#39;);</span><br><span class="line">        resolve(&#39;success&#39;);</span><br><span class="line">    &#125;, 1000);</span><br><span class="line">&#125;)</span><br><span class="line">const start &#x3D; Date.now();</span><br><span class="line">promise.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res, Date.now() - start);</span><br><span class="line">&#125;);</span><br><span class="line">promise.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res, Date.now() - start);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; timer</span><br><span class="line">&#x2F;&#x2F; success 1001</span><br><span class="line">&#x2F;&#x2F; success 1002</span><br></pre></td></tr></table></figure>

<p>执行结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#39;timer&#39;</span><br><span class="line">&#39;success&#39; 1001</span><br><span class="line">&#39;success&#39; 1002</span><br></pre></td></tr></table></figure>

<p>当然，如果你足够快的话，也可能两个都是<code>1001</code>。</p>
<p><code>Promise</code> 的 <code>.then</code> 或者 <code>.catch</code> 可以被调用多次，但这里 <code>Promise</code> 构造函数只执行一次。或者说 <code>promise</code> 内部状态一经改变，并且有了一个值，那么后续每次调用 <code>.then</code> 或者 <code>.catch</code> 都会直接拿到该值。</p>
<h4 id="3-6-题目六"><a href="#3-6-题目六" class="headerlink" title="3.6 题目六"></a>3.6 题目六</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve().then(() &#x3D;&gt; &#123;</span><br><span class="line">	return new Error(&#39;error!!!&#39;);</span><br><span class="line">&#125;).then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;then: &quot;, res);</span><br><span class="line">&#125;).catch(err &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&quot;catch: &quot;, err);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; then: Error: error!!!</span><br></pre></td></tr></table></figure>

<p>猜猜这里的结果输出的是什么 🤔️ ？</p>
<p>你可能想到的是进入<code>.catch</code>然后被捕获了错误。</p>
<p>结果并不是这样的，它走的是<code>.then</code>里面：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&quot;then: &quot; &quot;Error: error!!!</span><br></pre></td></tr></table></figure>

<p>这也验证了第4点和第6点，返回任意一个非 <code>promise</code> 的值都会被包裹成 <code>promise</code> 对象，因此这里的<code>return new Error(&#39;error!!!&#39;)</code>也被包裹成了<code>return Promise.resolve(new Error(&#39;error!!!&#39;))</code>。</p>
<p>当然如果你抛出一个错误的话，可以用下面两种方式的任意一种：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">return Promise.reject(new Error(&#39;error!!!&#39;));</span><br><span class="line">&#x2F;&#x2F; or</span><br><span class="line">throw new Error(&#39;error!!!&#39;)</span><br></pre></td></tr></table></figure>

<h4 id="3-7-题目七"><a href="#3-7-题目七" class="headerlink" title="3.7 题目七"></a>3.7 题目七</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">const promise &#x3D; Promise.resolve().then(() &#x3D;&gt; &#123;</span><br><span class="line">	return promise;</span><br><span class="line">&#125;)</span><br><span class="line">promise.catch(console.err);</span><br></pre></td></tr></table></figure>

<p><code>.then</code> 或 <code>.catch</code> 返回的值不能是 promise 本身，否则会造成死循环。</p>
<p>因此结果会报错：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Uncaught (in promise) TypeError: Chaining cycle detected for promise #&lt;Promise&gt;</span><br></pre></td></tr></table></figure>

<h4 id="3-8-题目八"><a href="#3-8-题目八" class="headerlink" title="3.8 题目八"></a>3.8 题目八</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve(1)</span><br><span class="line">    .then(2)</span><br><span class="line">    .then(Promise.resolve(3))</span><br><span class="line">    .then(console.log);</span><br><span class="line">&#x2F;&#x2F; 1（不是2也不是3）</span><br></pre></td></tr></table></figure>

<p>这道题看着好像很简单，又感觉很复杂的样子，怎么这么多个<code>.then</code>啊… </p>
<p>其实你只要记住<strong>原则8</strong>：<code>.then</code> 或者 <code>.catch</code> 的参数期望是函数，传入非函数则会发生值透传。</p>
<p>第一个<code>then</code>和第二个<code>then</code>中传入的都不是函数，一个是数字类型，一个是对象类型，因此发生了透传，将<code>resolve(1)</code> 的值直接传到最后一个<code>then</code>里。</p>
<p>所以输出结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1</span><br></pre></td></tr></table></figure>

<h4 id="3-9-题目九"><a href="#3-9-题目九" class="headerlink" title="3.9 题目九"></a>3.9 题目九</h4><p>下面来介绍一下<code>.then</code>函数中的两个参数。</p>
<p>第一个参数是用来处理<code>Promise</code>成功的函数，第二个则是处理失败的函数。</p>
<p>也就是说<code>Promise.resolve(&#39;1&#39;)</code>的值会进入成功的函数，<code>Promise.reject(&#39;2&#39;)</code>的值会进入失败的函数。</p>
<p>让我们来看看这个例子：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Promise.reject(&#39;err!!!&#39;)</span><br><span class="line">    .then((res) &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;success&#39;, res);</span><br><span class="line">    &#125;, (err) &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;error&#39;, err);</span><br><span class="line">    &#125;).catch(err &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;catch&#39;, err);</span><br><span class="line">    &#125;);</span><br><span class="line">&#x2F;&#x2F; error error!!!</span><br></pre></td></tr></table></figure>

<p>这里的执行结果是：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#39;error&#39; &#39;error!!!&#39;</span><br></pre></td></tr></table></figure>

<p>它进入的是<code>then()</code>中的第二个参数里面，而如果把第二个参数去掉，就进入了<code>catch()</code>中：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Promise.reject(&#39;error!!!&#39;)</span><br><span class="line">    .then((res) &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;success&#39;, res);</span><br><span class="line">    &#125;).catch(err &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;catch&#39;, err);</span><br><span class="line">    &#125;);</span><br><span class="line">&#x2F;&#x2F; catch error</span><br></pre></td></tr></table></figure>

<p>执行结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#39;catch&#39; &#39;error!!!&#39;</span><br></pre></td></tr></table></figure>

<p>但是有一个问题，如果是这个案例呢？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve()</span><br><span class="line">.then(function success (res) &#123;</span><br><span class="line">	throw new Error(&#39;error!!!&#39;);</span><br><span class="line">&#125;, function fail1 (err) &#123;</span><br><span class="line">	console.log(&#39;fail1&#39;, err);</span><br><span class="line">&#125;).catch(function fail2 (err) &#123;</span><br><span class="line">	console.log(&#39;fail2&#39;, err);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; fail2 Error: error!!!</span><br><span class="line">&#x2F;&#x2F;	at success</span><br></pre></td></tr></table></figure>

<p>由于<code>Promise</code>调用的是<code>resolve()</code>，因此<code>.then()</code>执行的应该是<code>success()</code>函数，可是<code>success()</code>函数抛出的是一个错误，它会被后面的<code>catch()</code>给捕获到，而不是被<code>fail1</code>函数捕获。</p>
<p>因此执行结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">fail2 Error: error!!!</span><br><span class="line">			at success</span><br></pre></td></tr></table></figure>

<h4 id="3-10-题目十"><a href="#3-10-题目十" class="headerlink" title="3.10 题目十"></a>3.10 题目十</h4><p>接着来看看<code>.finally()</code>，这个功能一般不太用在面试中，不过如果碰到了你也应该知道该如何处理。</p>
<p>其实你只要记住它三个很重要的知识点就可以了：</p>
<ol>
<li><code>.finally()</code>方法不管<code>Promise</code>对象最后的状态如何都会执行</li>
<li><code>.finally()</code>方法的回调函数不接受任何的参数，也就是说你在<code>.finally()</code>函数中是没法知道<code>Promise</code>最终的状态是<code>resolved</code>还是<code>rejected</code>的</li>
<li>它最终返回的默认会是一个<strong>上一次的Promise对象值</strong>，不过如果抛出的是一个异常则返回异常的<code>Promise</code>对象。</li>
</ol>
<p>来看看这个简单的例子：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve(&#39;1&#39;)</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;)</span><br><span class="line">.finally(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;finally&#39;);</span><br><span class="line">&#125;);</span><br><span class="line">Promise.resolve(&#39;2&#39;)</span><br><span class="line">.finally(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;finally2&#39;);</span><br><span class="line">    return &#39;我是finally2返回的值&#39;;</span><br><span class="line">&#125;)</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;finally2后面的then函数&#39;, res);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; finally2</span><br><span class="line">&#x2F;&#x2F; finally</span><br><span class="line">&#x2F;&#x2F; finally2后面的then函数 2</span><br></pre></td></tr></table></figure>

<p>这两个<code>Promise</code>的<code>.finally</code>都会执行，且就算<code>finally2</code>返回了新的值，它后面的<code>then()</code>函数接收到的结果却还是<code>&#39;2&#39;</code>，因此打印结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;1&#39;</span><br><span class="line">&#39;finally2&#39;</span><br><span class="line">&#39;finally&#39;</span><br><span class="line">&#39;finally2后面的then函数&#39; &#39;2&#39;</span><br></pre></td></tr></table></figure>

<p>至于为什么<code>finally2</code>的打印要在<code>finally</code>前面，请看下一个例子中的解析。</p>
<p>不过在此之前让我们再来确认一下，<code>finally</code>中要是抛出的是一个异常是怎样的：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve(&#39;1&#39;)</span><br><span class="line">.finally(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;finally1&#39;);</span><br><span class="line">    throw new Error(&#39;我是finally中抛出的异常&#39;);</span><br><span class="line">&#125;)</span><br><span class="line">.then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;finally后面的then函数&#39;, res);</span><br><span class="line">&#125;)</span><br><span class="line">.catch(err &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;捕获错误&#39;, err);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; finally1</span><br><span class="line">&#x2F;&#x2F; 捕获错误 Error: 我是finally中抛出的异常</span><br></pre></td></tr></table></figure>

<p>执行结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#39;finally1&#39;</span><br><span class="line">&#39;捕获错误&#39; Error: 我是finally中抛出的异常</span><br></pre></td></tr></table></figure>

<p>但是如果改为<code>return new Error(&#39;我是finally中抛出的异常&#39;)</code>，打印出来的就是<code>&#39;finally后面的then函数 1&#39;</code></p>
<p>让我们来看一个比较难的例子：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">function promise1 () &#123;</span><br><span class="line">    let p &#x3D; new Promise((resolve) &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;promise1&#39;);</span><br><span class="line">        resolve(&#39;1&#39;);</span><br><span class="line">    &#125;);</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">function promise2 () &#123;</span><br><span class="line">    return new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    	reject(&#39;error&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">promise1()</span><br><span class="line">    .then(res &#x3D;&gt; console.log(res))</span><br><span class="line">    .catch(err &#x3D;&gt; console.log(err))</span><br><span class="line">    .finally(() &#x3D;&gt; console.log(&#39;finally1&#39;));</span><br><span class="line"></span><br><span class="line">promise2()</span><br><span class="line">    .then(res &#x3D;&gt; console.log(res))</span><br><span class="line">    .catch(err &#x3D;&gt; console.log(err))</span><br><span class="line">    .finally(() &#x3D;&gt; console.log(&#39;finally2&#39;));</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; error</span><br><span class="line">&#x2F;&#x2F; finally1</span><br><span class="line">&#x2F;&#x2F; finally2</span><br></pre></td></tr></table></figure>

<p>执行过程：</p>
<ul>
<li>首先定义了两个函数<code>promise1</code>和<code>promise2</code>，先不管接着往下看。</li>
<li><code>promise1</code>函数先被调用了，然后执行里面<code>new Promise</code>的同步代码打印出<code>promise1</code></li>
<li>之后遇到了<code>resolve(1)</code>，将<code>p</code>的状态改为了<code>resolved</code>并将结果保存下来。</li>
<li>此时<code>promise1</code>内的函数内容已经执行完了，跳出该函数</li>
<li>碰到了<code>promise1().then()</code>，由于<code>promise1</code>的状态已经发生了改变且为<code>resolved</code>因此将<code>promise1().then()</code>这条微任务加入本轮的微任务列表(<strong>这是第一个微任务</strong>)</li>
<li>这时候要注意了，代码并不会接着往链式调用的下面走，也就是不会先将<code>.finally</code>加入微任务列表，那是因为<code>.then</code>本身就是一个微任务，它链式后面的内容必须得等当前这个微任务执行完才会执行，因此这里我们先不管<code>.finally()</code></li>
<li>再往下走碰到了<code>promise2()</code>函数，其中返回的<code>new Promise</code>中并没有同步代码需要执行，所以执行<code>reject(&#39;error&#39;)</code>的时候将<code>promise2</code>函数中的<code>Promise</code>的状态变为了<code>rejected</code></li>
<li>跳出<code>promise2</code>函数，遇到了<code>promise2().catch()</code>，将其加入当前的微任务队列(<strong>这是第二个微任务</strong>)，且链式调用后面的内容得等该任务执行完后才执行，和<code>.then()</code>一样。</li>
<li>OK， 本轮的宏任务全部执行完了，来看看微任务列表，存在<code>promise1().then()</code>，执行它，打印出<code>1</code>，然后遇到了<code>.finally()</code>这个微任务将它加入微任务列表(<strong>这是第三个微任务</strong>)等待执行</li>
<li>再执行<code>promise2().catch()</code>打印出<code>error</code>，执行完后将<code>finally2</code>加入微任务加入微任务列表(<strong>这是第四个微任务</strong>)</li>
<li>OK， 本轮又全部执行完了，但是微任务列表还有两个新的微任务没有执行完，因此依次执行<code>finally1</code>和<code>finally2</code>。</li>
</ul>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;1&#39;</span><br><span class="line">&#39;error&#39;</span><br><span class="line">&#39;finally1&#39;</span><br><span class="line">&#39;finally2&#39;</span><br></pre></td></tr></table></figure>

<p>在这道题中其实能拓展的东西挺多的，之前没有提到，那就是你可以理解为<strong>链式调用</strong>后面的内容需要等前一个调用执行完才会执行。</p>
<p>就像是这里的<code>finally()</code>会等<code>promise1().then()</code>执行完才会将<code>finally()</code>加入微任务队列，其实如果这道题中你把<code>finally()</code>换成是<code>then()</code>也是这样的:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">function promise1 () &#123;</span><br><span class="line">    let p &#x3D; new Promise((resolve) &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;promise1&#39;);</span><br><span class="line">        resolve(&#39;1&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">function promise2 () &#123;</span><br><span class="line">    return new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    	reject(&#39;error&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">promise1()</span><br><span class="line">.then(res &#x3D;&gt; console.log(res))</span><br><span class="line">.catch(err &#x3D;&gt; console.log(err))</span><br><span class="line">.then(() &#x3D;&gt; console.log(&#39;finally1&#39;));</span><br><span class="line"></span><br><span class="line">promise2()</span><br><span class="line">    .then(res &#x3D;&gt; console.log(res))</span><br><span class="line">    .catch(err &#x3D;&gt; console.log(err))</span><br><span class="line">    .then(() &#x3D;&gt; console.log(&#39;finally2&#39;));</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; error</span><br><span class="line">&#x2F;&#x2F; finally1</span><br><span class="line">&#x2F;&#x2F; finally2</span><br></pre></td></tr></table></figure>

<h3 id="4-Promise中的all和race"><a href="#4-Promise中的all和race" class="headerlink" title="4. Promise中的all和race"></a>4. Promise中的all和race</h3><p>在做下面的题目之前，让我们先来了解一下<code>Promise.all()</code>和<code>Promise.race()</code>的用法。</p>
<p>通俗来说，<code>.all()</code>的作用是接收一组异步任务，然后并行执行异步任务，并且在所有异步操作执行完后才执行回调。</p>
<p><code>.race()</code>的作用也是接收一组异步任务，然后并行执行异步任务，只保留取第一个执行完成的异步操作的结果，其他的方法仍在执行，不过执行结果会被抛弃。</p>
<p>来看看题目一。</p>
<h4 id="4-1-题目一"><a href="#4-1-题目一" class="headerlink" title="4.1 题目一"></a>4.1 题目一</h4><p>我们知道如果直接在脚本文件中定义一个<code>Promise</code>，它构造函数的第一个参数是会立即执行的，就像这样：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">const p1 &#x3D; new Promise(r &#x3D;&gt; console.log(&#39;立即打印&#39;));</span><br></pre></td></tr></table></figure>

<p>控制台中会立即打印出 “立即打印”。</p>
<p>因此为了控制它什么时候执行，我们可以用一个函数包裹着它，在需要它执行的时候，调用这个函数就可以了：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">function runP1 () &#123;</span><br><span class="line">    const p1 &#x3D; new Promise(r &#x3D;&gt; console.log(&#39;立即打印&#39;));</span><br><span class="line">    return p1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">runP1(); &#x2F;&#x2F; 调用此函数时才执行</span><br><span class="line">&#x2F;&#x2F; 立即打印</span><br></pre></td></tr></table></figure>

<p>让我们回归正题。</p>
<p>现在来构建这么一个函数：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function runAsync (x) &#123;</span><br><span class="line">    const p &#x3D; new Promise(r &#x3D;&gt; setTimeout(() &#x3D;&gt; r(x, console.log(x)), 1000));</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数传入一个值<code>x</code>，然后间隔一秒后打印出这个<code>x</code>。</p>
<p>如果我用<code>.all()</code>来执行它会怎样呢？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">function runAsync (x) &#123;</span><br><span class="line">    const p &#x3D; new Promise(r &#x3D;&gt; setTimeout(() &#x3D;&gt; r(x, console.log(x)), 1000));</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">Promise.all([runAsync(1), runAsync(2), runAsync(3)])</span><br><span class="line">  .then(res &#x3D;&gt; console.log(res));</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; 3</span><br><span class="line">&#x2F;&#x2F; [1, 2, 3]</span><br></pre></td></tr></table></figure>

<p>先来想想此段代码在浏览器中会如何执行？</p>
<p>没错，当你打开页面的时候，在间隔一秒后，控制台会同时打印出<code>1, 2, 3</code>，还有一个数组<code>[1, 2, 3]</code>。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">[1, 2, 3]</span><br></pre></td></tr></table></figure>

<p>所以你现在能理解这句话的意思了吗：<strong>有了all，你就可以并行执行多个异步操作，并且在一个回调中处理所有的返回数据。</strong></p>
<p><code>.all()</code>后面的<code>.then()</code>里的回调函数接收的就是所有异步操作的结果。</p>
<p>而且这个结果中数组的顺序和<code>Promise.all()</code>接收到的数组顺序一致！！！</p>
<blockquote>
<p>有一个场景是很适合用这个的，一些游戏类的素材比较多的应用，打开网页时，预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后，我们再进行页面的初始化。</p>
</blockquote>
<h4 id="4-2-题目二"><a href="#4-2-题目二" class="headerlink" title="4.2 题目二"></a>4.2 题目二</h4><p>我新增了一个<code>runReject</code>函数，它用来在<code>1000 * x</code>秒后<code>reject</code>一个错误。</p>
<p>同时<code>.catch()</code>函数能够捕获到<code>.all()</code>里最先的那个异常，并且只执行一次。</p>
<p>想想这道题会怎样执行呢？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">function runAsync (x) &#123;</span><br><span class="line">    const p &#x3D; new Promise(r &#x3D;&gt; setTimeout(() &#x3D;&gt; r(x, console.log(x)), 1000 * x));</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">function runReject (x) &#123;</span><br><span class="line">    const p &#x3D; new Promise((res, rej) &#x3D;&gt; setTimeout(() &#x3D;&gt; rej(&#96;Error: $&#123;x&#125;&#96;, console.log(x)), 1000 * x));</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)])</span><br><span class="line">    .then(res &#x3D;&gt; console.log(res))</span><br><span class="line">    .catch(err &#x3D;&gt; console.log(err));</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; error: Error: 2</span><br><span class="line">&#x2F;&#x2F; 3</span><br><span class="line">&#x2F;&#x2F; 4</span><br></pre></td></tr></table></figure>

<p>公布答案：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 1s后输出</span><br><span class="line">1</span><br><span class="line">&#x2F;&#x2F; 2s后输出</span><br><span class="line">2</span><br><span class="line">Error: 2</span><br><span class="line">&#x2F;&#x2F; 3s后输出</span><br><span class="line">3</span><br><span class="line">&#x2F;&#x2F; 4s后输出</span><br><span class="line">4</span><br></pre></td></tr></table></figure>

<p>没错，就像我之前说的，<code>.catch</code>是会捕获最先的那个异常，在这道题目中最先的异常就是<code>runReject(2)</code>的结果。</p>
<p>另外，如果一组异步操作中有一个异常都不会进入<code>.then()</code>的第一个回调函数参数中。</p>
<p>注意，为什么不说是不进入<code>.then()</code>中呢 ？</p>
<p>哈哈，大家别忘了<code>.then()</code>方法的第二个参数也是可以捕获错误的：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)])</span><br><span class="line">    .then(res &#x3D;&gt; console.log(res), </span><br><span class="line">    err &#x3D;&gt; console.log(err));</span><br></pre></td></tr></table></figure>

<h4 id="4-3-题目三"><a href="#4-3-题目三" class="headerlink" title="4.3 题目三"></a>4.3 题目三</h4><p>接下来让我们看看另一个有趣的方法<code>.race</code>。</p>
<p><code>race</code>，比赛，赛跑的意思。</p>
<p>所以使用<code>.race()</code>方法，它只会获取最先执行完成的那个结果，其它的异步任务虽然也会继续进行下去，不过<code>race</code>已经不管那些任务的结果了。</p>
<p>来，改造一下<code>4.1</code>这道题：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">function runAsync (x) &#123;</span><br><span class="line">    const p &#x3D; new Promise(r &#x3D;&gt; setTimeout(() &#x3D;&gt; r(x, console.log(x)), 1000));</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">Promise.race([runAsync(1), runAsync(2), runAsync(3)])</span><br><span class="line">    .then(res &#x3D;&gt; console.log(&#39;result: &#39;, res))</span><br><span class="line">    .catch(err &#x3D;&gt; console.log(err));</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; result: 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; 3</span><br></pre></td></tr></table></figure>

<p>执行结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">&#39;result: &#39; 1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td></tr></table></figure>

<blockquote>
<p>这个race有什么用呢？使用场景还是很多的，比如我们可以用race给某个异步请求设置超时时间，并且在超时后执行相应的操作</p>
</blockquote>
<h4 id="4-4-题目四"><a href="#4-4-题目四" class="headerlink" title="4.4 题目四"></a>4.4 题目四</h4><p>改造一下题目<code>4.2</code>：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">function runAsync(x) &#123;</span><br><span class="line">    const p &#x3D; new Promise(r &#x3D;&gt;</span><br><span class="line">    	setTimeout(() &#x3D;&gt; r(x, console.log(x)), 1000);</span><br><span class="line">    );</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">function runReject(x) &#123;</span><br><span class="line">    const p &#x3D; new Promise((res, rej) &#x3D;&gt;</span><br><span class="line">    	setTimeout(() &#x3D;&gt; rej(&#96;Error: $&#123;x&#125;&#96;, console.log(x)), 1000 * x);</span><br><span class="line">    );</span><br><span class="line">    return p;</span><br><span class="line">&#125;</span><br><span class="line">Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)])</span><br><span class="line">    .then(res &#x3D;&gt; console.log(&quot;result: &quot;, res))</span><br><span class="line">    .catch(err &#x3D;&gt; console.log(err));</span><br><span class="line">&#x2F;&#x2F; 0</span><br><span class="line">&#x2F;&#x2F; Error: 0</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; 3</span><br></pre></td></tr></table></figure>

<p>遇到错误的话，也是一样的，在这道题中，<code>runReject(0)</code>最先执行完，所以进入了<code>catch()</code>中：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">0</span><br><span class="line">&#39;Error: 0&#39;</span><br><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td></tr></table></figure>

<h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p>好的，让我们来总结一下<code>.then()</code>和<code>.race()</code>吧</p>
<ul>
<li><code>Promise.all()</code>的作用是接收一组异步任务，然后并行执行异步任务，并且在所有异步操作执行完后才执行回调。</li>
<li><code>.race()</code>的作用也是接收一组异步任务，然后并行执行异步任务，只保留取第一个执行完成的异步操作的结果，其他的方法仍在执行，不过执行结果会被抛弃。</li>
<li><code>Promise.all().then()</code>结果中数组的顺序和<code>Promise.all()</code>接收到的数组顺序一致。</li>
<li><code>all</code>和<code>race</code>传入的数组中如果有会抛出异常的异步任务，那么只有最先抛出的错误会被捕获，并且是被<code>then</code>的第二个参数或者后面的<code>catch</code>捕获；但并不会影响数组中其它的异步任务的执行。</li>
</ul>
<h3 id="5-async-await的几道题"><a href="#5-async-await的几道题" class="headerlink" title="5. async/await的几道题"></a>5. async/await的几道题</h3><p>既然谈到了<code>Promise</code>，那就肯定得再说说<code>async/await</code>，在很多时候<code>async</code>和<code>Promise</code>的解法差不多，又有些不一样。不信你来看看题目一。</p>
<h4 id="5-1-题目一"><a href="#5-1-题目一" class="headerlink" title="5.1 题目一"></a>5.1 题目一</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">async function async1() &#123;</span><br><span class="line">    console.log(&quot;async1 start&quot;);</span><br><span class="line">    await async2();</span><br><span class="line">    console.log(&quot;async1 end&quot;);</span><br><span class="line">&#125;</span><br><span class="line">async function async2() &#123;</span><br><span class="line">	console.log(&quot;async2&quot;);</span><br><span class="line">&#125;</span><br><span class="line">async1();</span><br><span class="line">console.log(&#39;start&#39;);</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; async2</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; async1 end</span><br></pre></td></tr></table></figure>

<p>这道基础题输出的是啥？</p>
<p>答案：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;async1 start&#39;</span><br><span class="line">&#39;async2&#39;</span><br><span class="line">&#39;start&#39;</span><br><span class="line">&#39;async1 end&#39;</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<ul>
<li>首先一进来是创建了两个函数的，我们先不看函数的创建位置，而是看它的调用位置</li>
<li>发现<code>async1</code>函数被调用了，然后去看看调用的内容</li>
<li>执行函数中的同步代码<code>async1 start</code>，之后碰到了<code>await</code>，它会阻塞<code>async1</code>后面代码的执行，因此会先去执行<code>async2</code>中的同步代码<code>async2</code>，然后跳出<code>async1</code></li>
<li>跳出<code>async1</code>函数后，执行同步代码<code>start</code></li>
<li>在一轮宏任务全部执行完之后，再来执行刚刚<code>await</code>后面的内容<code>async1 end</code>。</li>
</ul>
<p>在这里，你可以理解为「紧跟着await后面的语句相当于放到了new Promise中，下一行及之后的语句相当于放在Promise.then中」。</p>
<p>让我们来看看将<code>await</code>转换为<code>Promise.then</code>的伪代码：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">async function async1() &#123;</span><br><span class="line">    console.log(&quot;async1 start&quot;);</span><br><span class="line">    &#x2F;&#x2F; 原来代码</span><br><span class="line">    &#x2F;&#x2F; await async2();</span><br><span class="line">    &#x2F;&#x2F; console.log(&quot;async1 end&quot;);</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F; 转换后代码</span><br><span class="line">    new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&quot;async2&quot;);</span><br><span class="line">        resolve();</span><br><span class="line">    &#125;).then(res &#x3D;&gt; console.log(&quot;async1 end&quot;));</span><br><span class="line">&#125;</span><br><span class="line">async function async2() &#123;</span><br><span class="line">	console.log(&quot;async2&quot;);</span><br><span class="line">&#125;</span><br><span class="line">async1();</span><br><span class="line">console.log(&quot;start&quot;);</span><br></pre></td></tr></table></figure>

<p>转换后的伪代码和前面的执行结果是一样的。(感谢评论区<a target="_blank" rel="noopener" href="https://juejin.im/user/3421335914314061">Wing93</a>和<a target="_blank" rel="noopener" href="https://juejin.im/user/1926000100012317">Jexxie</a>小伙伴的指出)</p>
<p>另外关于<code>await</code>和<code>Promise</code>的区别，如果我们把<code>await async2()</code>换成一个<code>new Promise</code>呢？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">async function async1() &#123;</span><br><span class="line">    console.log(&quot;async1 start&quot;);</span><br><span class="line">    new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;promise&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">    console.log(&quot;async1 end&quot;);</span><br><span class="line">&#125;</span><br><span class="line">async1();</span><br><span class="line">console.log(&quot;start&quot;);</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; promise</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; async1 end</span><br></pre></td></tr></table></figure>

<p>此时的执行结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;async start&#39;</span><br><span class="line">&#39;promise&#39;</span><br><span class="line">&#39;async1 end&#39;</span><br><span class="line">&#39;start&#39;</span><br></pre></td></tr></table></figure>

<p>可以看到<code>new Promise()</code>并不会阻塞后面的同步代码<code>async1 end</code>的执行。</p>
<h4 id="5-2-题目二"><a href="#5-2-题目二" class="headerlink" title="5.2 题目二"></a>5.2 题目二</h4><p>现在将<code>async</code>结合定时器看看。</p>
<p>给题目一中的 <code>async2</code>函数中加上一个定时器：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">async function async1() &#123;</span><br><span class="line">    console.log(&quot;async1 start&quot;);</span><br><span class="line">    await async2();</span><br><span class="line">    console.log(&quot;async1 end&quot;);</span><br><span class="line">&#125;</span><br><span class="line">async function async2() &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;timer&#39;);</span><br><span class="line">    &#125;, 0)</span><br><span class="line">    console.log(&quot;async2&quot;);</span><br><span class="line">&#125;</span><br><span class="line">async1();</span><br><span class="line">console.log(&quot;start&quot;);</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; async2</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; async1 end</span><br><span class="line">&#x2F;&#x2F; timer</span><br></pre></td></tr></table></figure>

<p>没错，定时器始终还是最后执行的，它被放到下一条宏任务的延迟队列中。</p>
<p>答案：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#39;async1 start&#39;</span><br><span class="line">&#39;async2&#39;</span><br><span class="line">&#39;start&#39;</span><br><span class="line">&#39;async1 end&#39;</span><br><span class="line">&#39;timer&#39;</span><br></pre></td></tr></table></figure>

<h4 id="5-3-题目三"><a href="#5-3-题目三" class="headerlink" title="5.3 题目三"></a>5.3 题目三</h4><p>来吧，小伙伴们，让我们多加几个定时器看看。😁</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">async function async1() &#123;</span><br><span class="line">    console.log(&quot;async1 start&quot;);</span><br><span class="line">    await async2();</span><br><span class="line">    console.log(&quot;async1 end&quot;);</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;timer1&#39;);</span><br><span class="line">    &#125;, 0);</span><br><span class="line">&#125;</span><br><span class="line">async function async2() &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;timer2&#39;);</span><br><span class="line">    &#125;, 0)</span><br><span class="line">    console.log(&quot;async2&quot;);</span><br><span class="line">&#125;</span><br><span class="line">async1();</span><br><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;timer3&#39;);</span><br><span class="line">&#125;, 0);</span><br><span class="line">console.log(&quot;start&quot;);</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; async2</span><br><span class="line">&#x2F;&#x2F; start</span><br><span class="line">&#x2F;&#x2F; async1 end</span><br><span class="line">&#x2F;&#x2F; timer2</span><br><span class="line">&#x2F;&#x2F; timer3</span><br><span class="line">&#x2F;&#x2F; timer1</span><br></pre></td></tr></table></figure>

<p>思考一下，执行结果会是什么？</p>
<p>其实如果你能做到这里了，说明你前面的那些知识点也都掌握了，就不需要太过详细的步骤分析了。</p>
<p>直接公布答案吧：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#39;async1 start&#39;</span><br><span class="line">&#39;async2&#39;</span><br><span class="line">&#39;start&#39;</span><br><span class="line">&#39;async1 end&#39;</span><br><span class="line">&#39;timer2&#39;</span><br><span class="line">&#39;timer3&#39;</span><br><span class="line">&#39;timer1&#39;</span><br></pre></td></tr></table></figure>

<p>定时器谁先执行，你只需要关注谁先被调用的以及延迟时间是多少，这道题中延迟时间都是<code>0</code>，所以只要关注谁先被调用的。</p>
<h4 id="5-4-题目四"><a href="#5-4-题目四" class="headerlink" title="5.4 题目四"></a>5.4 题目四</h4><p>正常情况下，<code>async</code>中的<code>await</code>命令是一个<code>Promise</code>对象，返回该对象的结果。</p>
<p>但如果不是<code>Promise</code>对象的话，就会直接返回对应的值，相当于<code>Promise.resolve()</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">async function fn () &#123;</span><br><span class="line">    &#x2F;&#x2F; return await 1234</span><br><span class="line">    &#x2F;&#x2F; 等同于</span><br><span class="line">    return 123;</span><br><span class="line">&#125;</span><br><span class="line">fn().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">&#x2F;&#x2F; </span><br></pre></td></tr></table></figure>

<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">123</span><br></pre></td></tr></table></figure>

<h4 id="5-5-题目五"><a href="#5-5-题目五" class="headerlink" title="5.5 题目五"></a>5.5 题目五</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">async function async1 () &#123;</span><br><span class="line">    console.log(&#39;async1 start&#39;);</span><br><span class="line">    await new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;promise1&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">    console.log(&#39;async1 success&#39;);</span><br><span class="line">    return &#39;async1 end&#39;;</span><br><span class="line">&#125;</span><br><span class="line">console.log(&#39;srcipt start&#39;);</span><br><span class="line">async1().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">console.log(&#39;srcipt end&#39;);</span><br><span class="line">&#x2F;&#x2F; srcipt start</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; srcipt end</span><br></pre></td></tr></table></figure>

<p>这道题目比较有意思，大家要注意了。</p>
<p>在<code>async1</code>中<code>await</code>后面的<code>Promise</code>是没有返回值的，也就是它的状态始终是<code>pending</code>状态，因此相当于一直在<code>await</code>，<code>await</code>，<code>await</code>却始终没有响应…</p>
<p>所以在<code>await</code>之后的内容是不会执行的，也包括<code>async1</code>后面的 <code>.then</code>。</p>
<p>答案为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;script start&#39;</span><br><span class="line">&#39;async1 start&#39;</span><br><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;script end&#39;</span><br></pre></td></tr></table></figure>

<h4 id="5-6-题目六"><a href="#5-6-题目六" class="headerlink" title="5.6 题目六"></a>5.6 题目六</h4><p>让我们给<code>5.5</code>中的<code>Promise</code>加上<code>resolve</code>：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">async function async1 () &#123;</span><br><span class="line">    console.log(&#39;async1 start&#39;);</span><br><span class="line">    await new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;promise1&#39;);</span><br><span class="line">        resolve(&#39;promise1 resolve&#39;);</span><br><span class="line">    &#125;).then(res &#x3D;&gt; console.log(res))</span><br><span class="line">    console.log(&#39;async1 success&#39;);</span><br><span class="line">    return &#39;async1 end&#39;;</span><br><span class="line">&#125;</span><br><span class="line">console.log(&#39;srcipt start&#39;);</span><br><span class="line">async1().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">console.log(&#39;srcipt end&#39;);</span><br><span class="line">&#x2F;&#x2F; srcipt start</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; srcipt end</span><br><span class="line">&#x2F;&#x2F; promise1 resolve</span><br><span class="line">&#x2F;&#x2F; async1 success</span><br><span class="line">&#x2F;&#x2F; async1 end</span><br></pre></td></tr></table></figure>

<p>现在<code>Promise</code>有了返回值了，因此<code>await</code>后面的内容将会被执行：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#39;script start&#39;</span><br><span class="line">&#39;async1 start&#39;</span><br><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;script end&#39;</span><br><span class="line">&#39;promise1 resolve&#39;</span><br><span class="line">&#39;async1 success&#39;</span><br><span class="line">&#39;async1 end&#39;</span><br></pre></td></tr></table></figure>

<h4 id="5-7-题目七"><a href="#5-7-题目七" class="headerlink" title="5.7 题目七"></a>5.7 题目七</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">async function async1 () &#123;</span><br><span class="line">    console.log(&#39;async1 start&#39;);</span><br><span class="line">    await new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;promise1&#39;);</span><br><span class="line">        resolve(&#39;promise resolve&#39;);;</span><br><span class="line">    &#125;)</span><br><span class="line">    console.log(&#39;async1 success&#39;);</span><br><span class="line">    return &#39;async1 end&#39;;</span><br><span class="line">&#125;</span><br><span class="line">console.log(&#39;srcipt start&#39;);</span><br><span class="line">async1().then(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(res);</span><br><span class="line">&#125;)</span><br><span class="line">new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;promise2&#39;);</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;timer&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; srcipt start</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; promise2</span><br><span class="line">&#x2F;&#x2F; async1 success</span><br><span class="line">&#x2F;&#x2F; async1 end</span><br><span class="line">&#x2F;&#x2F; timer</span><br></pre></td></tr></table></figure>

<p>这道题应该也不难，不过有一点需要注意的，在<code>async1</code>中的<code>new Promise</code>它的<code>resovle</code>的值和<code>async1().then()</code>里的值是没有关系的，很多小伙伴可能看到<code>resovle(&#39;promise resolve&#39;)</code>就会误以为是<code>async1().then()</code>中的返回值。</p>
<p>因此这里的执行结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#39;script start&#39;</span><br><span class="line">&#39;async1 start&#39;</span><br><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;promise2&#39;</span><br><span class="line">&#39;async1 success&#39;</span><br><span class="line">&#39;async1 end&#39;</span><br><span class="line">&#39;timer&#39;</span><br></pre></td></tr></table></figure>

<h4 id="5-8-题目八"><a href="#5-8-题目八" class="headerlink" title="5.8 题目八"></a>5.8 题目八</h4><p>我们再来看一道字节跳动曾经的面试题：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">async function async1() &#123;</span><br><span class="line">    console.log(&quot;async1 start&quot;);</span><br><span class="line">    await async2();</span><br><span class="line">    console.log(&quot;async1 end&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">async function async2() &#123;</span><br><span class="line">	console.log(&quot;async2&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">console.log(&quot;script start&quot;);</span><br><span class="line"></span><br><span class="line">setTimeout(function() &#123;</span><br><span class="line">	console.log(&quot;setTimeout&quot;);</span><br><span class="line">&#125;, 0);</span><br><span class="line"></span><br><span class="line">async1();</span><br><span class="line"></span><br><span class="line">new Promise(function(resolve) &#123;</span><br><span class="line">    console.log(&quot;promise1&quot;);</span><br><span class="line">    resolve();</span><br><span class="line">&#125;).then(function() &#123;</span><br><span class="line">	console.log(&quot;promise2&quot;);</span><br><span class="line">&#125;);</span><br><span class="line">console.log(&#39;script end&#39;);</span><br><span class="line">&#x2F;&#x2F; script start</span><br><span class="line">&#x2F;&#x2F; async1 start</span><br><span class="line">&#x2F;&#x2F; async2</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; async1 end</span><br><span class="line">&#x2F;&#x2F; promise2</span><br><span class="line">&#x2F;&#x2F; setTimeout</span><br></pre></td></tr></table></figure>

<p>有了上面👆几题做基础，相信你很快也能答上来了。</p>
<p>自信的写下你们的答案吧。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#39;script start&#39;</span><br><span class="line">&#39;async1 start&#39;</span><br><span class="line">&#39;async2&#39;</span><br><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;script end&#39;</span><br><span class="line">&#39;async1 end&#39;</span><br><span class="line">&#39;promise2&#39;</span><br><span class="line">&#39;setTimeout&#39;</span><br></pre></td></tr></table></figure>

<p>(这道题最后<code>async1 end</code>和<code>promise2</code>的顺序其实在网上饱受争议，我这里使用浏览器<code>Chrome V80</code>，<code>Node v12.16.1</code>的执行结果都是上面这个答案)</p>
<h4 id="5-9-题目九"><a href="#5-9-题目九" class="headerlink" title="5.9 题目九"></a>5.9 题目九</h4><p>好的👌，<code>async/await</code>大法已练成，咱们继续：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">async function testSometing() &#123;</span><br><span class="line">    console.log(&quot;执行testSometing&quot;);</span><br><span class="line">    return &quot;testSometing&quot;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">async function testAsync() &#123;</span><br><span class="line">    console.log(&quot;执行testAsync&quot;);</span><br><span class="line">    return Promise.resolve(&quot;hello async&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">async function test() &#123;</span><br><span class="line">    console.log(&quot;test start...&quot;);</span><br><span class="line">    const v1 &#x3D; await testSometing();</span><br><span class="line">    console.log(v1);</span><br><span class="line">    const v2 &#x3D; await testAsync();</span><br><span class="line">    console.log(v2);</span><br><span class="line">    console.log(v1, v2);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">test();</span><br><span class="line"></span><br><span class="line">var promise &#x3D; new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&quot;promise start...&quot;);</span><br><span class="line">    resolve(&quot;promise&quot;);</span><br><span class="line">&#125;);</span><br><span class="line">promise.then(val &#x3D;&gt; console.log(val));</span><br><span class="line"></span><br><span class="line">console.log(&quot;test end...&quot;);</span><br><span class="line">&#x2F;&#x2F; test start...</span><br><span class="line">&#x2F;&#x2F; 执行testSometing</span><br><span class="line">&#x2F;&#x2F; promise start...</span><br><span class="line">&#x2F;&#x2F; test end...</span><br><span class="line">&#x2F;&#x2F; testSometing</span><br><span class="line">&#x2F;&#x2F; 执行testAsync</span><br><span class="line">&#x2F;&#x2F; promise</span><br><span class="line">&#x2F;&#x2F; hello async</span><br><span class="line">&#x2F;&#x2F; testSometing hello async</span><br></pre></td></tr></table></figure>

<p>答案：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#39;test start...&#39;</span><br><span class="line">&#39;执行testSometing&#39;</span><br><span class="line">&#39;promise start...&#39;</span><br><span class="line">&#39;test end...&#39;</span><br><span class="line">&#39;testSometing&#39;</span><br><span class="line">&#39;执行testAsync&#39;</span><br><span class="line">&#39;promise&#39;</span><br><span class="line">&#39;hello async&#39;</span><br><span class="line">&#39;testSometing&#39; &#39;hello async&#39;</span><br></pre></td></tr></table></figure>

<h3 id="6-async处理错误"><a href="#6-async处理错误" class="headerlink" title="6. async处理错误"></a>6. async处理错误</h3><h4 id="6-1-题目一"><a href="#6-1-题目一" class="headerlink" title="6.1 题目一"></a>6.1 题目一</h4><p>在<code>async</code>中，如果 <code>await</code>后面的内容是一个异常或者错误的话，会怎样呢？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">async function async1 () &#123;</span><br><span class="line">    await async2();</span><br><span class="line">    console.log(&#39;async1&#39;);</span><br><span class="line">    return &#39;async1 success&#39;;</span><br><span class="line">&#125;</span><br><span class="line">async function async2 () &#123;</span><br><span class="line">    return new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">        console.log(&#39;async2&#39;);</span><br><span class="line">        reject(&#39;error&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">async1().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">&#x2F;&#x2F; async2</span><br><span class="line">&#x2F;&#x2F; Uncaught (in promise) error</span><br></pre></td></tr></table></figure>

<p>例如这道题中，<code>await</code>后面跟着的是一个状态为<code>rejected</code>的<code>promise</code>。</p>
<p><strong>如果在async函数中抛出了错误，则终止错误结果，不会继续向下执行。</strong></p>
<p>所以答案为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#39;async2&#39;</span><br><span class="line">Uncaught (in promise) error</span><br></pre></td></tr></table></figure>

<p>如果改为<code>throw new Error</code>也是一样的：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">async function async1 () &#123;</span><br><span class="line">    console.log(&#39;async1&#39;);</span><br><span class="line">    throw new Error(&#39;error!!!&#39;);</span><br><span class="line">    return &#39;async1 success&#39;;</span><br><span class="line">&#125;</span><br><span class="line">async1().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">&#x2F;&#x2F; async1</span><br><span class="line">&#x2F;&#x2F; Uncaught (in promise) Error: error!!!</span><br></pre></td></tr></table></figure>

<p>结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#39;async1&#39;</span><br><span class="line">Uncaught (in promise) Error: error!!!</span><br></pre></td></tr></table></figure>

<h4 id="6-2-题目二"><a href="#6-2-题目二" class="headerlink" title="6.2 题目二"></a>6.2 题目二</h4><p>如果想要使得错误的地方不影响<code>async</code>函数后续的执行的话，可以使用<code>try catch</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">async function async1 () &#123;</span><br><span class="line">    try &#123;</span><br><span class="line">    	await Promise.reject(&#39;error!!!&#39;);</span><br><span class="line">    &#125; catch(e) &#123;</span><br><span class="line">    	console.log(e);</span><br><span class="line">    &#125;</span><br><span class="line">    console.log(&#39;async1&#39;);</span><br><span class="line">    return Promise.resolve(&#39;async1 success&#39;);</span><br><span class="line">&#125;</span><br><span class="line">async1().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">console.log(&#39;script start&#39;);</span><br><span class="line">&#x2F;&#x2F; script start</span><br><span class="line">&#x2F;&#x2F; error!!!</span><br><span class="line">&#x2F;&#x2F; async1</span><br><span class="line">&#x2F;&#x2F; async1 success</span><br></pre></td></tr></table></figure>

<p>这里的结果为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;script start&#39;</span><br><span class="line">&#39;error!!!&#39;</span><br><span class="line">&#39;async1&#39;</span><br><span class="line">&#39;async1 success&#39;</span><br></pre></td></tr></table></figure>

<p>或者你可以直接在<code>Promise.reject</code>后面跟着一个<code>catch()</code>方法：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">async function async1 () &#123;</span><br><span class="line">    &#x2F;&#x2F; try &#123;</span><br><span class="line">    &#x2F;&#x2F;   await Promise.reject(&#39;error!!!&#39;)</span><br><span class="line">    &#x2F;&#x2F; &#125; catch(e) &#123;</span><br><span class="line">    &#x2F;&#x2F;   console.log(e)</span><br><span class="line">    &#x2F;&#x2F; &#125;</span><br><span class="line">    await Promise.reject(&#39;error!!!&#39;)</span><br><span class="line">    	.catch(e &#x3D;&gt; console.log(e));</span><br><span class="line">    console.log(&#39;async1&#39;);</span><br><span class="line">    return Promise.resolve(&#39;async1 success&#39;);</span><br><span class="line">&#125;</span><br><span class="line">async1().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">console.log(&#39;script start&#39;);;</span><br><span class="line">&#x2F;&#x2F; script start</span><br><span class="line">&#x2F;&#x2F; error!!!</span><br><span class="line">&#x2F;&#x2F; async1</span><br><span class="line">&#x2F;&#x2F; async1 success</span><br></pre></td></tr></table></figure>

<p>运行结果是一样的。</p>
<h3 id="7-综合题"><a href="#7-综合题" class="headerlink" title="7. 综合题"></a>7. 综合题</h3><p>上面👆的题目都是被我拆分着说一些功能点，现在让我们来做一些比较难的综合题吧。</p>
<h4 id="7-1-题目一"><a href="#7-1-题目一" class="headerlink" title="7.1 题目一"></a>7.1 题目一</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">const first &#x3D; () &#x3D;&gt; (new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    console.log(3);</span><br><span class="line">    let p &#x3D; new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">        console.log(7);</span><br><span class="line">        setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">            console.log(5);</span><br><span class="line">            resolve(6);</span><br><span class="line">            console.log(p)</span><br><span class="line">        &#125;, 0)</span><br><span class="line">        resolve(1);</span><br><span class="line">    &#125;);</span><br><span class="line">    resolve(2);</span><br><span class="line">    p.then((arg) &#x3D;&gt; &#123;</span><br><span class="line">        console.log(arg);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;));</span><br><span class="line">first().then((arg) &#x3D;&gt; &#123;</span><br><span class="line">    console.log(arg);</span><br><span class="line">&#125;);</span><br><span class="line">console.log(4);</span><br><span class="line">&#x2F;&#x2F; 3</span><br><span class="line">&#x2F;&#x2F; 7</span><br><span class="line">&#x2F;&#x2F; 4</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; 2</span><br><span class="line">&#x2F;&#x2F; 5</span><br><span class="line">&#x2F;&#x2F; Promise&#123;&lt;fulfilled&gt;: 1&#125;</span><br></pre></td></tr></table></figure>

<p>过程分析：</p>
<ul>
<li>第一段代码定义的是一个函数，所以我们得看看它是在哪执行的，发现它在<code>4</code>之前，所以可以来看看<code>first</code>函数里面的内容了。(这一步有点类似于题目<code>1.5</code>)</li>
<li>函数<code>first</code>返回的是一个<code>new Promise()</code>，因此先执行里面的同步代码<code>3</code></li>
<li>接着又遇到了一个<code>new Promise()</code>，直接执行里面的同步代码<code>7</code></li>
<li>执行完<code>7</code>之后，在<code>p</code>中，遇到了一个定时器，先将它放到下一个宏任务队列里不管它，接着向下走</li>
<li>碰到了<code>resolve(1)</code>，这里就把<code>p</code>的状态改为了<code>resolved</code>，且返回值为<code>1</code>，不过这里也先不执行</li>
<li>跳出<code>p</code>，碰到了<code>resolve(2)</code>，这里的<code>resolve(2)</code>，表示的是把<code>first</code>函数返回的那个<code>Promise</code>的状态改了，也先不管它。</li>
<li>然后碰到了<code>p.then</code>，将它加入本次循环的微任务列表，等待执行</li>
<li>跳出<code>first</code>函数，遇到了<code>first().then()</code>，将它加入本次循环的微任务列表(<code>p.then</code>的后面执行)</li>
<li>然后执行同步代码<code>4</code></li>
<li>本轮的同步代码全部执行完毕，查找微任务列表，发现<code>p.then</code>和<code>first().then()</code>，依次执行，打印出<code>1和2</code></li>
<li>本轮任务执行完毕了，发现还有一个定时器没有跑完，接着执行这个定时器里的内容，执行同步代码<code>5</code></li>
<li>然后又遇到了一个<code>resolve(6)</code>，它是放在<code>p</code>里的，但是<code>p</code>的状态在之前已经发生过改变了，因此这里就不会再改变，也就是说<code>resolve(6)</code>相当于没任何用处，因此打印出来的<code>p</code>为<code>Promise&#123;&lt;resolved&gt;: 1&#125;</code>。(这一步类似于题目<code>3.1</code>)</li>
</ul>
<p>结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">3</span><br><span class="line">7</span><br><span class="line">4</span><br><span class="line">1</span><br><span class="line">2</span><br><span class="line">5</span><br><span class="line">Promise&#123;&lt;fulfilled&gt;: 1&#125;</span><br></pre></td></tr></table></figure>

<h4 id="7-2-题目二"><a href="#7-2-题目二" class="headerlink" title="7.2 题目二"></a>7.2 题目二</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">const async1 &#x3D; async () &#x3D;&gt; &#123;</span><br><span class="line">    console.log(&#39;async1&#39;);</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">   		console.log(&#39;timer1&#39;);</span><br><span class="line">    &#125;, 2000)</span><br><span class="line">    await new Promise(resolve &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(&#39;promise1&#39;);</span><br><span class="line">    &#125;)</span><br><span class="line">    console.log(&#39;async1 end&#39;);</span><br><span class="line">    return &#39;async1 success&#39;;</span><br><span class="line">&#125; </span><br><span class="line">console.log(&#39;script start&#39;);</span><br><span class="line">async1().then(res &#x3D;&gt; console.log(res));</span><br><span class="line">console.log(&#39;script end&#39;);</span><br><span class="line">Promise.resolve(1)</span><br><span class="line">    .then(2)</span><br><span class="line">    .then(Promise.resolve(3))</span><br><span class="line">    .catch(4)</span><br><span class="line">    .then(res &#x3D;&gt; console.log(res));</span><br><span class="line">setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;timer2&#39;);</span><br><span class="line">&#125;, 1000);</span><br><span class="line">&#x2F;&#x2F; script start</span><br><span class="line">&#x2F;&#x2F; async1</span><br><span class="line">&#x2F;&#x2F; promise1</span><br><span class="line">&#x2F;&#x2F; script end</span><br><span class="line">&#x2F;&#x2F; 1</span><br><span class="line">&#x2F;&#x2F; timer2</span><br><span class="line">&#x2F;&#x2F; timer1</span><br></pre></td></tr></table></figure>

<p>注意的知识点：</p>
<ul>
<li><code>async</code>函数中<code>await</code>的<code>new Promise</code>要是没有返回值的话则不执行后面的内容(类似题<code>5.5</code>)</li>
<li><code>.then</code>函数中的参数期待的是函数，如果不是函数的话会发生透传(类似题<code>3.8</code> )</li>
<li>注意定时器的延迟时间</li>
</ul>
<p>因此本题答案为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#39;script start&#39;</span><br><span class="line">&#39;async1&#39;</span><br><span class="line">&#39;promise1&#39;</span><br><span class="line">&#39;script end&#39;</span><br><span class="line">1</span><br><span class="line">&#39;timer2&#39;</span><br><span class="line">&#39;timer1&#39;</span><br></pre></td></tr></table></figure>

<h4 id="7-3-题目三"><a href="#7-3-题目三" class="headerlink" title="7.3 题目三"></a>7.3 题目三</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">const p1 &#x3D; new Promise((resolve) &#x3D;&gt; &#123;</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        resolve(&#39;resolve3&#39;);</span><br><span class="line">        console.log(&#39;timer1&#39;);</span><br><span class="line">    &#125;, 0);</span><br><span class="line">    resolve(&#39;resovle1&#39;);</span><br><span class="line">    resolve(&#39;resolve2&#39;);</span><br><span class="line">&#125;).then(res &#x3D;&gt; &#123;</span><br><span class="line">    console.log(res);</span><br><span class="line">    setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    	console.log(p1);</span><br><span class="line">    &#125;, 1000)</span><br><span class="line">&#125;).finally(res &#x3D;&gt; &#123;</span><br><span class="line">	console.log(&#39;finally&#39;, res);</span><br><span class="line">&#125;);</span><br><span class="line">&#x2F;&#x2F; resovle1</span><br><span class="line">&#x2F;&#x2F; finally: undefined</span><br><span class="line">&#x2F;&#x2F; timer1</span><br><span class="line">&#x2F;&#x2F; Promise&#123;&lt;fulfilled&gt;: undefined&#125;</span><br></pre></td></tr></table></figure>

<p>注意的知识点：</p>
<ul>
<li><code>Promise</code>的状态一旦改变就无法改变(类似题目<code>3.5</code>)</li>
<li><code>finally</code>不管<code>Promise</code>的状态是<code>resolved</code>还是<code>rejected</code>都会执行，且它的回调函数是接收不到<code>Promise</code>的结果的，所以<code>finally()</code>中的<code>res</code>是一个迷惑项(类似<code>3.10</code>)。</li>
<li>最后一个定时器打印出的<code>p1</code>其实是<code>.finally</code>的返回值，我们知道<code>.finally</code>的返回值如果在没有抛出错误的情况下默认会是上一个<code>Promise</code>的返回值(<code>3.10</code>中也有提到), 而这道题中<code>.finally</code>上一个<code>Promise</code>是<code>.then()</code>，但是这个<code>.then()</code>并没有返回值，所以<code>p1</code>打印出来的<code>Promise</code>的值会是<code>undefined</code>，如果你在定时器的<strong>下面</strong>加上一个<code>return 1</code>，则值就会变成<code>1</code>(感谢掘友<a target="_blank" rel="noopener" href="https://juejin.im/user/2260251637193639">JS丛中过</a>的指出)。</li>
</ul>
<p>答案：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#39;resolve1&#39;</span><br><span class="line">&#39;finally&#39; undefined</span><br><span class="line">&#39;timer1&#39;</span><br><span class="line">Promise&#123;&lt;resolved&gt;: undefined&#125;</span><br></pre></td></tr></table></figure>

<h3 id="8-Promise-自测面试题（由易到难-满分100分）"><a href="#8-Promise-自测面试题（由易到难-满分100分）" class="headerlink" title="8. Promise 自测面试题（由易到难 | 满分100分）"></a>8. Promise 自测面试题（由易到难 | 满分100分）</h3><h4 id="8-1-题目一（5分）"><a href="#8-1-题目一（5分）" class="headerlink" title="8.1 题目一（5分）"></a>8.1 题目一（5分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Promise</span>.resolve()</span><br><span class="line">    .then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">&#x27;error!!!&#x27;</span>);</span><br><span class="line">    &#125;)</span><br><span class="line">    .then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;then:&#x27;</span> + res);</span><br><span class="line">    &#125;)</span><br><span class="line">    .catch(<span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;catch:&#x27;</span> + err);</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="comment">// then:Error: error!!!</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript">then:<span class="hljs-built_in">Error</span>: error!!!
</code></pre>
<p>第一题热身题，应该不成问题，还是解释一下： <code>Promise</code>是 <code>resolve</code>成功状态，那么就会执行第一个<code>then</code> 回调，返回值是 <code>Error</code>对象，那么就会封装一个 <code>Promise.resolve(参数为Error对象)</code>，然后又执行第二个 <code>then</code> 回调，那么打印结果如上所示。</p>
<p></p>
</details>

<h4 id="8-2-题目二（5分）"><a href="#8-2-题目二（5分）" class="headerlink" title="8.2 题目二（5分）"></a>8.2 题目二（5分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> promise = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    resolve(<span class="string">&#x27;success1&#x27;</span>);</span><br><span class="line">    reject(<span class="string">&#x27;error&#x27;</span>);</span><br><span class="line">    resolve(<span class="string">&#x27;success2&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">promise</span><br><span class="line">    .then(<span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;then:&#x27;</span> + res);</span><br><span class="line">    &#125;)</span><br><span class="line">    .catch(<span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;catch:&#x27;</span> + err);</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="comment">// then:success1</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript">then:success1
</code></pre>
<p>本题主要考察 <code>promise</code> 的固化，一旦状态改变就不会再改变了！</p>
<p></p>
</details>

<h4 id="8-3-题目三（10分）"><a href="#8-3-题目三（10分）" class="headerlink" title="8.3 题目三（10分）"></a>8.3 题目三（10分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> promise = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="number">1</span>);</span><br><span class="line">    resolve();</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="number">2</span>);</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">promise.then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="number">3</span>);</span><br><span class="line">&#125;)</span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">4</span>);</span><br><span class="line"><span class="comment">// 1</span></span><br><span class="line"><span class="comment">// 2</span></span><br><span class="line"><span class="comment">// 4</span></span><br><span class="line"><span class="comment">// 3</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript"><span class="hljs-number">1</span>
<span class="hljs-number">2</span>
<span class="hljs-number">4</span>
<span class="hljs-number">3</span></code></pre>
<p>本题与事件循环相关，<code>Promise</code> 构造函数内部的<strong>执行器函数内部</strong>属于同步代码，<code>.then</code> 注册的回调函数属于<strong>微任务</strong>，那么会先输出同步代码 <code>1</code>，遇到 <code>resolve()</code> 并不会阻止后面同步代码的执行，因为并没有 <code>return</code> 语句。然后将微任务加入微任务队列，之后打印同步代码 <code>2</code>，之后继续先打印同步代码 <code>4</code>，最后取出微任务队列中的任务元素，打印 <code>3</code>，因此打印结果为 <code>1 2 4 3</code>。</p>
<p></p>
</details>

<h4 id="8-4-题目四（10分）"><a href="#8-4-题目四（10分）" class="headerlink" title="8.4 题目四（10分）"></a>8.4 题目四（10分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> p1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    reject(<span class="number">42</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">p1.catch((<span class="function"><span class="keyword">function</span> (<span class="params">value</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(value);</span><br><span class="line">    <span class="keyword">return</span> value + <span class="number">1</span>;</span><br><span class="line">&#125;)).then(<span class="function"><span class="keyword">function</span> (<span class="params">value</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(value);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 42</span></span><br><span class="line"><span class="comment">// 43</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript"><span class="hljs-number">42</span>
<span class="hljs-number">43</span></code></pre>
<p>解释： <code>p1</code> 是返回的 <code>reject</code> 状态的 <code>promise</code>，那么就会走 <code>catch</code>，首先就会打印 <code>42</code>，然后遇到 <code>return</code>语句，返回的是普通值，那么就会封装成 <code>Promise.resolve(43)</code>，那么就会执行后面的 <code>then</code> 回调，打印 <code>43</code>。</p>
<p></p>
</details>

<h4 id="8-5-题目五（10分）"><a href="#8-5-题目五（10分）" class="headerlink" title="8.5 题目五（10分）"></a>8.5 题目五（10分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> p1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    resolve(<span class="number">42</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> p2 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    reject(<span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">&#x27;TypeError!!!&#x27;</span>));</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">p1.then(<span class="function"><span class="keyword">function</span> (<span class="params">value</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(value);</span><br><span class="line">    <span class="keyword">return</span> p2;</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params">value</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(value);</span><br><span class="line">&#125;, <span class="function"><span class="keyword">function</span> (<span class="params">err</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(err);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 43</span></span><br><span class="line"><span class="comment">// Error: TypeError!!!</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript"><span class="hljs-number">42</span>
<span class="hljs-attr">Error</span>: <span class="hljs-built_in">TypeError</span>!!!</code></pre>
<p>解释一下，打印 <code>42</code>我想应该不用解释了，我们注意 <code>p1</code> 执行 <code>.then</code> 回调时返回的是 <code>p2</code>，而 p2 是失败的 <code>promise</code>状态，那么就不会像上一题一样进行 <code>promise.resolve()</code>的封装了，直接返回失败的状态，那么就只会执行 <code>then</code> 回调的第二个 <code>err</code> 那条路了。</p>
<p></p>
</details>

<h4 id="8-6-题目六（10分）"><a href="#8-6-题目六（10分）" class="headerlink" title="8.6 题目六（10分）"></a>8.6 题目六（10分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;timer1&#x27;</span>);</span><br><span class="line">    <span class="built_in">Promise</span>.resolve().then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;promise1&#x27;</span>);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="built_in">Promise</span>.resolve().then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise2&#x27;</span>);</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;timer2&#x27;</span>);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// promise2</span></span><br><span class="line"><span class="comment">// timer1</span></span><br><span class="line"><span class="comment">// promise1</span></span><br><span class="line"><span class="comment">// timer2</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript">promise2
timer1
promise1
timer2
</code></pre>
<p>这题也是考察事件循环相关，首先遇到 <code>setTimeout</code>，加入宏任务队列，然后遇到 <code>Promise.resolve().then</code>微任务，加入微任务队列，此时主线程没有同步代码可执行，先拿出微任务队列中的人物执行，先执行同步代码 <code>promise2</code>，然后遇到 <code>setTimeout</code>，加入宏任务队列。此时微任务执行完毕，取出宏任务队列中的任务，依次执行即可，打印输出结果。</p>
<p></p>
</details>

<h4 id="8-7-题目七（10分）"><a href="#8-7-题目七（10分）" class="headerlink" title="8.7 题目七（10分）"></a>8.7 题目七（10分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Promise</span>.resolve()</span><br><span class="line">    .then(<span class="function">() =&gt;</span> &#123; <span class="comment">// 外层第一个then</span></span><br><span class="line">        <span class="built_in">Promise</span>.resolve().then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="number">1</span>);</span><br><span class="line">        &#125;).then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="number">2</span>);</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">    .then(<span class="function">() =&gt;</span> &#123; <span class="comment">// 外层第二个then</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="number">3</span>);</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="comment">// 1</span></span><br><span class="line"><span class="comment">// 3</span></span><br><span class="line"><span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript"><span class="hljs-number">1</span>
<span class="hljs-number">3</span>
<span class="hljs-number">2</span></code></pre>
<p>这道题很容易做错，你可能会想着打印出 <code>1 2 3</code>。</p>
<blockquote>
<p>感谢评论区 <code>@Vincent-y</code> 老哥的指正</p>
</blockquote>
<p>这里解释一下，先将外层第一个 <code>then</code> 压入微任务列表，等待这个 <code>then</code> 执行完返回一个 <code>promise</code> 之后再将外层第二个 <code>then</code> 压入微任务队列吧，第一个then里面的逻辑同样如此。</p>
<p></p>
</details>

<h4 id="8-8-题目八（10分）"><a href="#8-8-题目八（10分）" class="headerlink" title="8.8 题目八（10分）"></a>8.8 题目八（10分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">await</span> async2();</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;async1 end&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;async2 end&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line">async1();</span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">10</span>);</span><br><span class="line"><span class="comment">// async2 end</span></span><br><span class="line"><span class="comment">// 10</span></span><br><span class="line"><span class="comment">// async1 end</span></span><br></pre></td></tr></table></figure>

<details><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript">async2 end
<span class="hljs-number">10</span>
async1 end
<span class="copy-code-btn">复制代码</span></code></pre>
<p>这题考察了 <code>async/await</code>，在执行 <code>async1</code> 函数时，遇到 <code>await async2();</code> 这段代码，而 <code>async2</code>函数是个同步函数，直接输出 <code>async2 end</code>，然后因为是 <code>await</code>，返回的是 <code>promise</code>对象，返回值是 <code>async2()</code>执行的结果，即默认的 <code>undefined</code>，之后的代码属于微任务，加入微任务队列，此时再走同步代码，输出 <code>10</code>，之后，主线程已经执行完毕，然后去找微任务队列，取出之前加入的微任务，输出 <code>async1 end</code>。</p>
<p></p>
</details>

<p>下面，我们还可以对上述代码进行一个变形，如下代码所示：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">await</span> async2();</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;async1 end&#x27;</span>);</span><br><span class="line">        <span class="built_in">console</span>.log(err);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;async2 end&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(<span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">&#x27;error!!!&#x27;</span>));</span><br><span class="line">&#125;</span><br><span class="line">async1();</span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">10</span>);</span><br><span class="line"><span class="comment">// async2 end</span></span><br><span class="line"><span class="comment">// 10</span></span><br><span class="line"><span class="comment">// async1 end</span></span><br><span class="line"><span class="comment">// Error: error!!!</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript">async2 end
<span class="hljs-number">10</span>
async1 end
<span class="hljs-attr">Error</span>: error!!!</code></pre>
<p>这里要注意的就是对于 <code>await</code> 返回 <code>reject</code> 状态，必须要用 <code>try / catch</code> 进行捕获错误，不然就会报错！</p>
<p></p>
</details>

<h4 id="8-9-题目九（15分）"><a href="#8-9-题目九（15分）" class="headerlink" title="8.9 题目九（15分）"></a>8.9 题目九（15分）</h4><blockquote>
<p>下面这道题是特别特别经典的一道题了！</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;async1 start&#x27;</span>);</span><br><span class="line">    <span class="keyword">await</span> async2();</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;async1 end&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;async2&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;script start&#x27;</span>);</span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;setTimeout&#x27;</span>);</span><br><span class="line">&#125;, <span class="number">0</span>)</span><br><span class="line">async1();</span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise1&#x27;</span>);</span><br><span class="line">    resolve();</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise2&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;script end&#x27;</span>);</span><br><span class="line"><span class="comment">// script start</span></span><br><span class="line"><span class="comment">// async1 start</span></span><br><span class="line"><span class="comment">// async2</span></span><br><span class="line"><span class="comment">// promise1</span></span><br><span class="line"><span class="comment">// script end</span></span><br><span class="line"><span class="comment">// async1 end</span></span><br><span class="line"><span class="comment">// promise2</span></span><br><span class="line"><span class="comment">// setTimeout</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><blockquote>
<p>总体思路就是：先执行宏任务（当前代码块也算是宏任务），然后执行当前宏任务产生的微任务，然后接着执行宏任务</p>
</blockquote>
<ul>
<li>从上往下执行代码，先执行同步代码，输出 <code>script start</code></li>
<li>遇到 <code>setTimeout</code> ，现把 <code>setTimeout</code> 的代码放到宏任务队列中</li>
<li>执行 <code>async1()</code>，输出 <code>async1 start</code>, 然后执行 <code>async2()</code>, 输出 <code>async2</code>，把 <code>async2()</code> 后面的代码 <code>console.log('async1 end')</code>放到微任务队列中</li>
<li>接着往下执行，输出 <code>promise1</code>，把 .then() 放到微任务队列中；<strong>注意 Promise 本身是同步的立即执行函数，.then是异步执行函数</strong></li>
<li>接着往下执行， 输出 <code>script end</code>。同步代码（同时也是宏任务）执行完成，接下来开始执行刚才放到微任务中的代码</li>
<li>依次执行微任务中的代码，依次输出 <code>async1 end</code>、 <code>promise2</code>, 微任务中的代码执行完成后，开始执行宏任务中的代码，输出 <code>setTimeout</code></li>
</ul>
<p>最后结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript">script start
async1 start
async2
promise1
script end
async1 end
promise2
<span class="hljs-built_in">setTimeout</span></code></pre>
<p></p>
</details>

<h4 id="8-10-题目十（15分）"><a href="#8-10-题目十（15分）" class="headerlink" title="8.10 题目十（15分）"></a>8.10 题目十（15分）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> b = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise1&#x27;</span>);</span><br><span class="line">    resolve();</span><br><span class="line">&#125;).then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise2&#x27;</span>);</span><br><span class="line">&#125;).then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise3&#x27;</span>);</span><br><span class="line">&#125;).then(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise4&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">a = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="keyword">async</span> (resolve, reject) =&gt; &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(a);</span><br><span class="line">    <span class="keyword">await</span> b;</span><br><span class="line">    <span class="built_in">console</span>.log(a);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;after1&#x27;</span>);</span><br><span class="line">    <span class="keyword">await</span> a;</span><br><span class="line">    resolve(<span class="literal">true</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;after2&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;end&#x27;</span>);</span><br><span class="line"><span class="comment">// promise1</span></span><br><span class="line"><span class="comment">// undefined</span></span><br><span class="line"><span class="comment">// end</span></span><br><span class="line"><span class="comment">// promise2</span></span><br><span class="line"><span class="comment">// promise3</span></span><br><span class="line"><span class="comment">// promise4</span></span><br><span class="line"><span class="comment">// Promise &#123; pending &#125;</span></span><br><span class="line"><span class="comment">// after1</span></span><br></pre></td></tr></table></figure>

<details open=""><summary><b>查看答案</b></summary>
<p>
</p><p>输出结果如下：</p>
<pre><code class="hljs language-javascript copyable" lang="javascript">promise1
<span class="hljs-literal">undefined</span>
end
promise2
promise3
promise4
<span class="hljs-built_in">Promise</span> &#123; &lt;pending&gt; &#125;
after1
</code></pre>
<p>这道题是一道综合性比较强的题，但是如果理解了前面9道题，这道题应该问题也不是很大的，现在来解释一波：</p>
<p>首先， <code>new Promise</code>里面是同步代码，会优先打印 <code>promise1</code>。然后注册了三个 <code>then</code> 的回调，加入微任务队列。</p>
<p>之后来到下一个  <code>new Promise</code>，此时的 <code>a</code> 还没有接收到任务返回值，那么就是默认值 <code>undefined</code>。</p>
<p>然后遇到 <code>await b</code>，然而 b 是一个promise 的实例， 已经在之前通过 new Promise 执行了，是三个微任务，之后先去找找看还有没有同步代码，于是找到了输出 <code>end</code>。</p>
<p>此时主线程同步代码已经执行完毕，去找微任务，依次打印 <code>promise2 promise3 promise4</code>。</p>
<p>而 <code>await b</code> 也是返回 <code>promise</code> 对象，即封装好的 <code>Promise.resolve(undefined)</code>。然而没有进行返回和接受。</p>
<p>之后执行输出 <code>a</code>的那行代码，此时主线程同步代码已经执行完了，那么 <code>a</code> 也会返回一个 <code>Promise</code>，但是状态没有发生变化，因此打印的是 <code>Promise &#123; &lt;pending&gt; &#125;</code>。</p>
<p>然后执行输出 <code>after1</code>。</p>
<p>然后遇到 <code>await a</code>，而此时 <code>a</code>还是 <code>pending</code>，因此后面回调代码不会执行，这也是这道题的小坑，很容易跳进去！</p></details>


    </div>

    
    
    
      
<div>
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
</div>
        

  <div class="followme">
    <p>欢迎关注我的其它发布渠道</p>

    <div class="social-list">

        <div class="social-item">
          <a target="_blank" class="social-link" href="/atom.xml">
            <span class="icon">
              <i class="fa fa-rss"></i>
            </span>

            <span class="label">RSS</span>
          </a>
        </div>
    </div>
  </div>


      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/JavaScript/" rel="tag"><i class="fa fa-tag"></i> JavaScript</a>
              <a href="/tags/%E9%9D%A2%E8%AF%95/" rel="tag"><i class="fa fa-tag"></i> 面试</a>
              <a href="/tags/Promise/" rel="tag"><i class="fa fa-tag"></i> Promise</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2021/04/13/40%E9%81%93this%E9%9D%A2%E8%AF%95%E9%A2%98+%E6%89%8B%E5%86%99new,call,apply,bind/" rel="prev" title="40道this面试题+手写new,call,apply,bind">
      <i class="fa fa-chevron-left"></i> 40道this面试题+手写new,call,apply,bind
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/04/20/%E9%B2%9C%E4%B8%BA%E4%BA%BA%E7%9F%A5%E7%9A%84JavaScript%E5%8A%9F%E8%83%BD/" rel="next" title="鲜为人知的JavaScript功能">
      鲜为人知的JavaScript功能 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          
    <div class="comments" id="valine-comments"></div>

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#0-%E5%89%8D%E6%9C%9F%E5%87%86%E5%A4%87"><span class="nav-text">0.前期准备</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-Promise%E7%9A%84%E5%87%A0%E9%81%93%E5%9F%BA%E7%A1%80%E9%A2%98"><span class="nav-text">1. Promise的几道基础题</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-1-%E9%A2%98%E7%9B%AE%E4%B8%80"><span class="nav-text">1.1 题目一</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-2-%E9%A2%98%E7%9B%AE%E4%BA%8C"><span class="nav-text">1.2 题目二</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-3-%E9%A2%98%E7%9B%AE%E4%B8%89"><span class="nav-text">1.3 题目三</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-4-%E9%A2%98%E7%9B%AE%E5%9B%9B"><span class="nav-text">1.4 题目四</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-5-%E9%A2%98%E7%9B%AE%E4%BA%94"><span class="nav-text">1.5 题目五</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-6-%E9%A2%98%E7%9B%AE%E5%85%AD"><span class="nav-text">1.6 题目六</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-Promise%E7%BB%93%E5%90%88setTimeout"><span class="nav-text">2. Promise结合setTimeout</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-%E9%A2%98%E7%9B%AE%E4%B8%80"><span class="nav-text">2.1 题目一</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-2-%E9%A2%98%E7%9B%AE%E4%BA%8C"><span class="nav-text">2.2 题目二</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-%E9%A2%98%E7%9B%AE%E4%B8%89"><span class="nav-text">2.3 题目三</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-%E9%A2%98%E7%9B%AE%E4%B8%89-1"><span class="nav-text">2.3 题目三</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-4-%E9%A2%98%E7%9B%AE%E5%9B%9B"><span class="nav-text">2.4 题目四</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-5-%E9%A2%98%E7%9B%AE%E4%BA%94"><span class="nav-text">2.5 题目五</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-Promise%E4%B8%AD%E7%9A%84then%E3%80%81catch%E3%80%81finally"><span class="nav-text">3. Promise中的then、catch、finally</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%80%BB%E7%BB%93%EF%BC%9A"><span class="nav-text">总结：</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-1-%E9%A2%98%E7%9B%AE%E4%B8%80"><span class="nav-text">3.1 题目一</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-%E9%A2%98%E7%9B%AE%E4%BA%8C"><span class="nav-text">3.2 题目二</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-%E9%A2%98%E7%9B%AE%E4%B8%89"><span class="nav-text">3.3 题目三</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-4-%E9%A2%98%E7%9B%AE%E5%9B%9B"><span class="nav-text">3.4 题目四</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-5-%E9%A2%98%E7%9B%AE%E4%BA%94"><span class="nav-text">3.5 题目五</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-6-%E9%A2%98%E7%9B%AE%E5%85%AD"><span class="nav-text">3.6 题目六</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-7-%E9%A2%98%E7%9B%AE%E4%B8%83"><span class="nav-text">3.7 题目七</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-8-%E9%A2%98%E7%9B%AE%E5%85%AB"><span class="nav-text">3.8 题目八</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-9-%E9%A2%98%E7%9B%AE%E4%B9%9D"><span class="nav-text">3.9 题目九</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-10-%E9%A2%98%E7%9B%AE%E5%8D%81"><span class="nav-text">3.10 题目十</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-Promise%E4%B8%AD%E7%9A%84all%E5%92%8Crace"><span class="nav-text">4. Promise中的all和race</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-1-%E9%A2%98%E7%9B%AE%E4%B8%80"><span class="nav-text">4.1 题目一</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-2-%E9%A2%98%E7%9B%AE%E4%BA%8C"><span class="nav-text">4.2 题目二</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-3-%E9%A2%98%E7%9B%AE%E4%B8%89"><span class="nav-text">4.3 题目三</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-4-%E9%A2%98%E7%9B%AE%E5%9B%9B"><span class="nav-text">4.4 题目四</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%80%BB%E7%BB%93"><span class="nav-text">总结</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-async-await%E7%9A%84%E5%87%A0%E9%81%93%E9%A2%98"><span class="nav-text">5. async&#x2F;await的几道题</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#5-1-%E9%A2%98%E7%9B%AE%E4%B8%80"><span class="nav-text">5.1 题目一</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-2-%E9%A2%98%E7%9B%AE%E4%BA%8C"><span class="nav-text">5.2 题目二</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-3-%E9%A2%98%E7%9B%AE%E4%B8%89"><span class="nav-text">5.3 题目三</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-4-%E9%A2%98%E7%9B%AE%E5%9B%9B"><span class="nav-text">5.4 题目四</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-5-%E9%A2%98%E7%9B%AE%E4%BA%94"><span class="nav-text">5.5 题目五</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-6-%E9%A2%98%E7%9B%AE%E5%85%AD"><span class="nav-text">5.6 题目六</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-7-%E9%A2%98%E7%9B%AE%E4%B8%83"><span class="nav-text">5.7 题目七</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-8-%E9%A2%98%E7%9B%AE%E5%85%AB"><span class="nav-text">5.8 题目八</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-9-%E9%A2%98%E7%9B%AE%E4%B9%9D"><span class="nav-text">5.9 题目九</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6-async%E5%A4%84%E7%90%86%E9%94%99%E8%AF%AF"><span class="nav-text">6. async处理错误</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#6-1-%E9%A2%98%E7%9B%AE%E4%B8%80"><span class="nav-text">6.1 题目一</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#6-2-%E9%A2%98%E7%9B%AE%E4%BA%8C"><span class="nav-text">6.2 题目二</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7-%E7%BB%BC%E5%90%88%E9%A2%98"><span class="nav-text">7. 综合题</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#7-1-%E9%A2%98%E7%9B%AE%E4%B8%80"><span class="nav-text">7.1 题目一</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#7-2-%E9%A2%98%E7%9B%AE%E4%BA%8C"><span class="nav-text">7.2 题目二</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#7-3-%E9%A2%98%E7%9B%AE%E4%B8%89"><span class="nav-text">7.3 题目三</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#8-Promise-%E8%87%AA%E6%B5%8B%E9%9D%A2%E8%AF%95%E9%A2%98%EF%BC%88%E7%94%B1%E6%98%93%E5%88%B0%E9%9A%BE-%E6%BB%A1%E5%88%86100%E5%88%86%EF%BC%89"><span class="nav-text">8. Promise 自测面试题（由易到难 | 满分100分）</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#8-1-%E9%A2%98%E7%9B%AE%E4%B8%80%EF%BC%885%E5%88%86%EF%BC%89"><span class="nav-text">8.1 题目一（5分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-2-%E9%A2%98%E7%9B%AE%E4%BA%8C%EF%BC%885%E5%88%86%EF%BC%89"><span class="nav-text">8.2 题目二（5分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-3-%E9%A2%98%E7%9B%AE%E4%B8%89%EF%BC%8810%E5%88%86%EF%BC%89"><span class="nav-text">8.3 题目三（10分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-4-%E9%A2%98%E7%9B%AE%E5%9B%9B%EF%BC%8810%E5%88%86%EF%BC%89"><span class="nav-text">8.4 题目四（10分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-5-%E9%A2%98%E7%9B%AE%E4%BA%94%EF%BC%8810%E5%88%86%EF%BC%89"><span class="nav-text">8.5 题目五（10分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-6-%E9%A2%98%E7%9B%AE%E5%85%AD%EF%BC%8810%E5%88%86%EF%BC%89"><span class="nav-text">8.6 题目六（10分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-7-%E9%A2%98%E7%9B%AE%E4%B8%83%EF%BC%8810%E5%88%86%EF%BC%89"><span class="nav-text">8.7 题目七（10分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-8-%E9%A2%98%E7%9B%AE%E5%85%AB%EF%BC%8810%E5%88%86%EF%BC%89"><span class="nav-text">8.8 题目八（10分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-9-%E9%A2%98%E7%9B%AE%E4%B9%9D%EF%BC%8815%E5%88%86%EF%BC%89"><span class="nav-text">8.9 题目九（15分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#8-10-%E9%A2%98%E7%9B%AE%E5%8D%81%EF%BC%8815%E5%88%86%EF%BC%89"><span class="nav-text">8.10 题目十（15分）</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="hxy"
      src="/images/Robben.gif">
  <p class="site-author-name" itemprop="name">hxy</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">80</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">8</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">120</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/huxingyi1997" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;huxingyi1997" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:huxingyi1997@zju.edu.cn" title="E-Mail → mailto:huxingyi1997@zju.edu.cn" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-frog"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">hxy</span>
</div>

<div class="theme-info">
  <div class="powered-by"></div>
  <span class="post-count">博客全站共1039.2k字</span>
</div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/lozad@1/dist/lozad.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : true,
      appId      : 'pQsO3ySbU4VtWN2j1FLA74Ha-gzGzoHsz',
      appKey     : 'QYacMDY2VY7Wazprg1X6FiUv',
      placeholder: "Just go go",
      avatar     : 'mm',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : false,
      lang       : 'zh-cn' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

  
  <!-- 动态背景特效 -->
  <!-- 樱花特效 -->
    <script async src="/js/src/sakura.js"></script>
    <script async src="/js/src/fairyDustCursor.js"></script>
</body>
</html>
